Makuhari Development Corporation
14 min read, 2672 words, last updated: 2026/3/6
TwitterLinkedInFacebookEmail

日本の標準地域メッシュコードと PostGIS で都市環境を定量化する

はじめに

「この地点は住みやすいのか?」という問いに、データで答えようとしたことはありますか?

日本には、国土を均一なグリッドで分割する標準地域メッシュという仕組みがあります。JIS C 6304 で規格化されたこの体系は、国勢調査・気象観測・環境アセスメントなど公的統計の空間集計基盤として 50 年以上運用されています。

この記事では、標準地域メッシュの構造を解説し、PostGIS と組み合わせることで「都市環境を定量的にスコアリングする」実装パターンを紹介します。不動産テック、都市計画、ロケーションインテリジェンスなど、空間分析を必要とするプロダクト開発者向けの内容です。


標準地域メッシュとは

階層構造

標準地域メッシュは、日本全土を段階的に細分化するグリッドシステムです。上位メッシュを4分割して下位メッシュを生成する再帰的な構造を持ちます。

レベル 名称 辺の長さ(概算) コード桁数 メッシュ数(全国)
1次メッシュ 地域メッシュ 約80km 4桁 約176
2次メッシュ 統合地域メッシュ 約10km 6桁 約4,500
3次メッシュ 基準地域メッシュ 約1km 8桁 約380,000
4次メッシュ 2分の1地域メッシュ 約500m 9桁 約1,520,000
5次メッシュ 4分の1地域メッシュ 約250m 10桁 約6,080,000

コード体系

メッシュコードは緯度・経度から一意に決定されます。上位メッシュのコードが下位メッシュの接頭辞になるため、文字列前方一致で親子関係を判定できます。

1次メッシュ(4桁)

コード = [緯度×1.5の整数部(2桁)] + [経度-100の整数部(2桁)]

例:東京駅 (35.6812, 139.7671)
  → 緯度部: floor(35.6812 × 1.5) = floor(53.5218) = 53
  → 経度部: 139 - 100 = 39
  → 1次メッシュコード: 5339

2次メッシュ(6桁):1次メッシュを緯度方向8等分・経度方向8等分して 64 分割。

コード = [1次(4桁)] + [緯度8分割位置(1桁)] + [経度8分割位置(1桁)]

例:東京駅 → 533945

3次以降:さらに 10 等分(3次)→ 2等分(4次)→ 2等分(5次)と再帰的に細分化。

なぜメッシュコードが優れているか

  1. 座標から一意計算:テーブル参照不要、算術計算のみで変換できる
  2. 階層的な包含関係:コード前方一致で空間包含を高速判定
  3. 均一グリッド:面積が統一されているため、密度比較が直感的
  4. 公的統計との親和性:e-Stat、国土数値情報など日本の公的データの多くがメッシュ単位で公開

PostGIS でメッシュを扱う

テーブル設計

メッシュ単位で都市環境データを格納する基本的なテーブル設計です。

CREATE TABLE mesh_metrics (
    mesh_code VARCHAR(10) PRIMARY KEY,  -- 250mメッシュ
    geom GEOMETRY(Polygon, 4326),       -- メッシュ境界ポリゴン
    population INTEGER,                  -- 人口(国勢調査)
    elevation_avg REAL,                  -- 平均標高
    hazard_flags JSONB,                  -- 災害リスクフラグ
    env_scores JSONB,                    -- 環境スコア
    updated_at TIMESTAMPTZ DEFAULT now()
);
 
-- 空間インデックス
CREATE INDEX idx_mesh_geom ON mesh_metrics USING GIST(geom);
-- コード前方一致検索用
CREATE INDEX idx_mesh_code ON mesh_metrics (mesh_code text_pattern_ops);

設計ポイント

  • mesh_code を主キーにすることで、座標→コード変換後に PK 直引きが可能(O(1) ルックアップ)
  • JSONB カラムで可変の指標群を柔軟に格納
  • text_pattern_ops インデックスで前方一致(LIKE '5339%')を高速化

座標からメッシュコードへの変換

PostGIS の関数として実装すると、SQL クエリ内で直接利用できます。

CREATE OR REPLACE FUNCTION lat_lng_to_mesh_250m(
    lat DOUBLE PRECISION,
    lng DOUBLE PRECISION
) RETURNS VARCHAR(10) AS $$
DECLARE
    lat_idx INTEGER; lng_idx INTEGER;
    m1_lat INTEGER; m1_lng INTEGER;
    m2_lat INTEGER; m2_lng INTEGER;
    m3_lat INTEGER; m3_lng INTEGER;
    m4 INTEGER; m5 INTEGER;
    rem_lat DOUBLE PRECISION; rem_lng DOUBLE PRECISION;
BEGIN
    -- 1次メッシュ
    m1_lat := floor(lat * 1.5)::INTEGER;
    m1_lng := (floor(lng) - 100)::INTEGER;
    rem_lat := lat * 1.5 - m1_lat;
    rem_lng := lng - floor(lng);
 
    -- 2次メッシュ (8分割)
    m2_lat := floor(rem_lat * 8)::INTEGER;
    m2_lng := floor(rem_lng * 8)::INTEGER;
    rem_lat := rem_lat * 8 - m2_lat;
    rem_lng := rem_lng * 8 - m2_lng;
 
    -- 3次メッシュ (10分割)
    m3_lat := floor(rem_lat * 10)::INTEGER;
    m3_lng := floor(rem_lng * 10)::INTEGER;
    rem_lat := rem_lat * 10 - m3_lat;
    rem_lng := rem_lng * 10 - m3_lng;
 
    -- 4次 (2分割)
    m4 := floor(rem_lat * 2)::INTEGER * 2 + floor(rem_lng * 2)::INTEGER + 1;
    rem_lat := rem_lat * 2 - floor(rem_lat * 2);
    rem_lng := rem_lng * 2 - floor(rem_lng * 2);
 
    -- 5次 (2分割)
    m5 := floor(rem_lat * 2)::INTEGER * 2 + floor(rem_lng * 2)::INTEGER + 1;
 
    RETURN lpad(m1_lat::TEXT, 2, '0')
        || lpad(m1_lng::TEXT, 2, '0')
        || m2_lat::TEXT || m2_lng::TEXT
        || m3_lat::TEXT || m3_lng::TEXT
        || m4::TEXT || m5::TEXT;
END;
$$ LANGUAGE plpgsql IMMUTABLE STRICT;

これにより、任意の座標からメッシュデータを直接引ける:

SELECT env_scores, hazard_flags
FROM mesh_metrics
WHERE mesh_code = lat_lng_to_mesh_250m(35.6812, 139.7671);

階層集計

メッシュコードの前方一致を利用すると、異なるスケールの集計が簡単に実現できます。

-- 1km メッシュ単位(3次メッシュ)で人口を集計
SELECT
    left(mesh_code, 8) AS mesh_1km,
    SUM(population) AS total_pop,
    AVG((env_scores->>'convenience')::REAL) AS avg_convenience
FROM mesh_metrics
WHERE mesh_code LIKE '5339%'  -- 東京周辺の1次メッシュ
GROUP BY left(mesh_code, 8);

都市環境スコアリングのアーキテクチャ

多層データ統合

メッシュを空間集計の単位とし、複数のデータソースを統合するアーキテクチャを紹介します。

graph TD subgraph データソース A["国勢調査<br/>人口・世帯"] B["国土数値情報<br/>災害・地形"] C["POI データ<br/>施設・店舗"] D["衛星データ<br/>地表面温度"] end subgraph 空間結合 E["250m メッシュ<br/>グリッド生成"] A -->|"メッシュ集計"| E B -->|"ST_Intersects"| E C -->|"半径カウント"| E D -->|"ラスタ抽出"| E end subgraph スコアリング E --> F["指標正規化<br/>百分位ランク"] F --> G["mesh_metrics<br/>テーブル格納"] end subgraph クエリ G -->|"PK直引き < 5ms"| H["API レスポンス"] end

データソース別の結合パターン

データ種別 結合方法
点データ(POI) メッシュ中心点からの半径カウント 保育園・病院・コンビニ
面データ(ハザード) ST_Intersects で重なり判定 浸水想定区域・土砂災害
メッシュ統計 コード直結合 国勢調査人口・世帯構成
ラスタデータ ST_Value でメッシュ中心値を抽出 地表面温度・標高
ネットワーク 外部エンジンで最寄り距離を計算 駅・IC への距離

百分位ランクによる正規化

異なる単位・スケールの指標を比較可能にするため、百分位ランク(percentile rank)を用います。

-- 各メッシュの指標を百分位ランクに変換
WITH ranked AS (
    SELECT
        mesh_code,
        (env_scores->>'convenience')::REAL AS convenience,
        PERCENT_RANK() OVER (
            ORDER BY (env_scores->>'convenience')::REAL
        ) AS pct_rank
    FROM mesh_metrics
    WHERE mesh_code LIKE '5339%'
)
SELECT mesh_code, convenience, round(pct_rank * 100) AS percentile
FROM ranked
WHERE mesh_code = '5339451234';

利点

  • 「上位 20% に入る利便性」のような直感的な表現が可能
  • 都道府県内・広域圏内など、比較母集団を切り替えることで相対評価のスケールを調整できる
  • 外れ値に頑健(min-max 正規化と異なり極端な値の影響を受けない)

パフォーマンス最適化

プリコンピュート vs リアルタイム

メッシュベースのスコアリングでは、プリコンピュート(事前計算) が圧倒的に有利です。

戦略 レスポンス 用途
プリコンピュート(PK直引き) < 5ms 変化の遅い指標(人口・災害・環境)
リアルタイム空間検索 30-80ms ユーザー指定の半径・動的な条件
混合 10-30ms KNN + プリコンピュート結合

メッシュの利点は、座標→コード変換が算術計算のみで完結するため、空間インデックスを経由せずにプリコンピュート結果を PK で直引きできる ことです。これは ST_ContainsST_DWithin による空間検索よりも桁違いに高速です。

首都圏スケールでの実績

250m メッシュで首都圏(東京・神奈川・千葉・埼玉)をカバーする場合、約 117,000 メッシュが対象になります。

  • メッシュテーブルのサイズ:約 50MB(インデックス含む)
  • PK 直引きレスポンス:< 1ms
  • 全メッシュスキャン(集計クエリ):< 500ms
  • バッチ更新(全メッシュ再計算):数分〜十数分

このスケールであれば、PostgreSQL の単一テーブルで十分に実用的です。


応用例

1. 住環境総合スコア

複数指標の百分位ランクを重み付き平均して、メッシュ単位の「住みやすさスコア」を算出。

SELECT
    mesh_code,
    (
        (env_scores->>'convenience')::REAL * 0.3 +
        (env_scores->>'safety')::REAL * 0.25 +
        (env_scores->>'childcare')::REAL * 0.2 +
        (env_scores->>'transit')::REAL * 0.25
    ) AS livability_score
FROM mesh_metrics
ORDER BY livability_score DESC
LIMIT 100;

2. エリア比較

メッシュコードの階層を利用して、市区町村レベルの比較を即座に生成。

-- 行政区画 × メッシュの空間結合で区別集計
SELECT
    a.city_name,
    AVG((m.env_scores->>'convenience')::REAL) AS avg_convenience,
    AVG((m.env_scores->>'safety')::REAL) AS avg_safety,
    COUNT(*) AS mesh_count
FROM mesh_metrics m
JOIN admin_boundary a ON ST_Contains(a.geom, m.geom)
WHERE a.prefecture = '東京都'
GROUP BY a.city_name
ORDER BY avg_convenience DESC;

3. 時系列変化の検出

同じメッシュコードで異なる時点のデータを比較することで、都市の変化を定量的に追跡できます。メッシュコードは座標から一意に決まるため、時系列での突合が容易です。


実装上の注意点

メッシュ境界の扱い

メッシュの境界線上にある点は、どちらのメッシュに帰属させるかの一貫したルールが必要です。JIS 規格では「北端・東端は含まない(左下閉・右上開)」が原則ですが、floor 関数で変換する場合はこの挙動が自然に実現されます。

海域・離島の除外

250m メッシュを全国生成すると海域メッシュが大量に発生します。陸域のみを対象とする場合は、海岸線ポリゴンとの ST_Intersects でフィルタリングするか、人口 > 0 のメッシュのみを扱うことで回避できます。

データソースの更新頻度

データ 更新周期 対応
国勢調査 5年 次回データ公開時にバッチ更新
ハザードマップ 不定期 公開通知時に手動トリガー
POI 月次〜年次 定期バッチ + 差分更新
衛星データ 日次〜月次 自動パイプライン

まとめ

日本の標準地域メッシュは、50 年の運用実績を持つ空間集計の国家規格です。PostGIS と組み合わせることで:

  • 座標→メッシュコード変換が算術計算のみで完結し、PK 直引きで < 5ms のレスポンスを実現
  • 階層的なコード体系により、250m から 80km まで同一のデータ構造でマルチスケール分析が可能
  • 公的統計との直接結合により、人口・災害・環境データを統一フレームワークで統合

不動産テック、都市計画、ロケーションインテリジェンスなどの空間分析プロダクトにおいて、メッシュベースのアーキテクチャは「事前計算 + PK 直引き」による高速レスポンスと、階層集計の柔軟性を両立する強力な選択肢です。


この記事の内容は、筆者が GIS ベースの不動産分析サービスを開発する過程で得た知見に基づいています。

Makuhari Development Corporation
法人番号: 6040001134259
ご利用にあたって
個人情報保護方針
個人情報取扱に関する同意事項
お問い合わせ
Copyright© Makuhari Development Corporation. All Rights Reserved.