別名・略称:マッピング処理
ジオコーディング は住所や地名を緯度経度に変換する処理、 地図化 はその位置情報をコロプレス図・点プロット・ヒートマップに可視化する処理。 SSDSE-B-2026 の都道府県データを folium や plotly で日本地図上に色塗りするのが典型的な応用。
「住所→座標→地図描画→空間統計」 が地理情報処理の標準フロー。
🍰 まずはやさしく
住所と座標を入れ替える翻訳機です。
地図に場所を表示するために使います。
スマホの地図アプリで店を探すときです。
変換の方法と便利な道具について読みます。
ジオコード変換(Geocoding):住所と緯度経度の相互変換
🍰 まずはやさしく
住所を数字の座標に変える橋渡しです。
データの場所を地図で見るために使います。
都道府県の名前を位置に変えるときです。
分析の前に行う準備の手順について読みます。
🍰 まずはやさしく
住所を点として地図に打つ作業です。
場所が正しいか確かめるために使います。
県庁所在地の位置を点にする例です。
図を使って正しく変換できたか読みます。
東京都千代田区永田町1-7-1緯度 35.6759, 経度 139.7448(35.6895, 139.6917)東京都新宿区西新宿2丁目ジオコーディングは「住所→緯度経度」 という単純な変換に見えますが、 結果を統計的に評価するには 「変換精度の分布」「都道府県間の整合性」「時系列での座標ドリフト」 という三つの視点が必要です。 ここでは SSDSE-B-2026 の都道府県をジオコーディング対象とみなし、 拡張の図 3 点・表 3 点・Python 実装を提示します。
図1 のような散布図は、 ジオコーディング結果の品質チェックに不可欠です。 もし 1 点だけ大西洋上にプロットされていたら、 それは住所の表記ゆれ(例えば「東京」 と「東京駅前」 の混同)を疑うべきサインです。 数値の桁誤り(35.69 を 3.569 と書いた等)も視覚的に検出できます。
図2 のように誤差を可視化すると、 「中央値 5m、 最大 2km」 のようなサマリ統計が読み取れます。 SSDSE-B-2026 のように都道府県単位なら問題は少ないですが、 市町村・町丁目レベルでは API による差が大きく出るため、 必ずこの種の分布チェックを行うべきです。
図3 は、 ジオコーディング結果と統計データを重ね合わせる典型例です。 地理座標に「定量データ」 を結びつけることで、 単なる位置情報が意味のある地理分析に変わります。 これがジオコーディングを学ぶ最大の動機です。
| API | 無償枠 | 日本対応 | 教育用途 |
|---|---|---|---|
| Google Maps API | 200 USD/月 | ◎ | ○(要クレカ登録) |
| Nominatim (OSM) | フリー | ○ | ◎ |
| 国土地理院 API | フリー | ◎ | ◎ |
| Geocoding.jp | フリー | ◎ | ◎ |
| HERE API | 月 25 万件 | ○ | ○ |
| Mapbox | 月 10 万件 | ○ | ○ |
| 県 | 県庁所在地 | 緯度 | 経度 | 人口(万) |
|---|---|---|---|---|
| 北海道 | 札幌市 | 43.064 | 141.347 | 509 |
| 東京都 | 新宿区 | 35.690 | 139.692 | 1,409 |
| 大阪府 | 大阪市 | 34.687 | 135.520 | 876 |
| 愛知県 | 名古屋市 | 35.181 | 136.907 | 748 |
| 福岡県 | 福岡市 | 33.607 | 130.418 | 510 |
| 沖縄県 | 那覇市 | 26.213 | 127.681 | 147 |
※ 人口(万) は SSDSE-B-2026 の 2023 年断面(総人口 A1101)を万人単位に丸めた概数。 緯度経度は各県庁所在地の代表点。
| 誤差要因 | 影響度 | SSDSE での対策 |
|---|---|---|
| 住所表記ゆれ | 高 | 前処理で正規化 |
| 市町村合併 | 中 | 時点を明示 |
| 範囲ジオコード | 中 | 代表点を選定 |
| 座標系違い (WGS84 vs JGD2011) | 低 | 統一する |
| 海外住所混入 | 低 | 国判定でフィルタ |
| API レート制限 | 中 | バッチ + キャッシュ |
このコードでやること:SSDSE-B-2026 の人口列と、 別途用意した都道府県中心点 CSV をマージし、 緯度経度ベースの簡易マップ(matplotlib 散布図)を描画する。
📥 入力データ (例):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | import pandas as pd import matplotlib.pyplot as plt # SSDSE-B-2026 は cp932。2行目の日本語見出しは header=1 で除外し、 # 1行目の列コード(A1101=総人口 等)をヘッダーとして読む ssdse = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', header=1) # 都道府県庁の緯度経度マスター(別途用意した CSV, 列: Prefecture,緯度,経度) geo = pd.read_csv('data/raw/pref_centroids.csv', encoding='utf-8') # 最新年(2023年)の都道府県別 総人口(A1101) を抽出 latest = ssdse[ssdse['SSDSE-B-2026'] == 2023][['Prefecture', 'A1101']] # 都道府県名(Prefecture)で緯度経度マスターと結合 merged = latest.merge(geo, on='Prefecture') # 総人口を円の大きさにしたバブルマップ plt.figure(figsize=(8, 6)) plt.scatter(merged['経度'], merged['緯度'], s=merged['A1101'] / 20000, alpha=0.6, color='steelblue', edgecolor='black') plt.xlabel('経度'); plt.ylabel('緯度') plt.title('都道府県別 総人口バブルマップ (SSDSE-B-2026, 2023年)') plt.grid(True, alpha=0.3) plt.savefig('pref_population_map.png', dpi=100) print(merged.head()) |
📤 実行すると次の出力が得られる:
💬 結果の読み方:太平洋ベルト(東京・名古屋・大阪・福岡)の円が大きく、 東北・四国・山陰の円が小さい。 ジオコーディングと統計データを組み合わせることで、 数字だけでは見えない「地理的偏在」が一目で分かる。 SSDSE-B-2026 を使うと、 こうした可視化を手元の環境で 5 分で再現できる。
以上の図表と実装を組み合わせることで、 ジオコーディングは「単なる住所変換」 から「データ分析の入り口」 へと変わる。 SSDSE-B-2026 と緯度経度マスターを連結するだけで、 47 都道府県の地理的特性を可視化・統計化できる。
ジオコーディングを実務で使いこなすために、 既存の解説をさらに補強し、 理解度チェックを設置する。 ジオコーディングは「住所文字列を緯度経度に変換する」 という単純な処理に見えるが、 実際には住所表記の揺らぎ・市町村合併・JR 駅名と住所名の混同等、 多数の落とし穴がある。 SSDSE-B-2026 の都道府県データと地理空間データを結合する際には、 「都道府県コード経由で結合する」 のが最も安全。
| API | 精度 | 制限 | 商用利用 | 推奨用途 |
|---|---|---|---|---|
| Google Geocoding API | 世界最高水準 | 有料 (月 200 USD 無料枠あり) | 可 | 商用・本番システム |
| OpenStreetMap (Nominatim) | 地域差大 | 1 req/sec、 大量利用は自前サーバ | 条件付き可 (ODbL) | 研究・小規模 |
| HEREMaps API | 高精度 | 有料 | 可 | 商用・モビリティ |
| 国土地理院ジオコーディング | 日本国内特化 | 無料・要登録 | 条件付き可 | 日本国内データ |
| 位置参照情報ダウンロードサービス (国土数値情報) | 都道府県・市町村単位 | 無料 | 可 | SSDSE-B-2026 等の都道府県・市町村集計データ |
| Esri ArcGIS World Geocoding | 高精度 | 有料 | 可 | GIS 統合・企業 |
| Mapbox Geocoding API | 高精度 | 有料 (無料枠 10 万 req/月) | 可 | 地図アプリ統合 |
→ SSDSE-B-2026 のような都道府県単位のデータでは、 国土地理院や国土数値情報のような無料の公的ジオコーディングが最も適している。 個人住所を含むデータでは Google や HEREMaps の有料 API が精度的に優位。 用途に応じた API 選択が、 ジオコーディング作業の質を決定する。
| 失敗パターン | 原因 | 対処 |
|---|---|---|
| 住所表記揺らぎ | 「東京都」 vs「東京」、「1丁目」 vs「一丁目」 | 正規化前処理、 半角全角統一 |
| 市町村合併 | 「平成の大合併」 で旧地名が消失 | 合併履歴データベースで補正 |
| 同名地名 | 「中央区」 が東京・大阪・新潟等に存在 | 都道府県名で曖昧性解消 |
| API レート制限 | 大量住所を一括変換で 429 エラー | バッチ処理、 リトライ機構、 キャッシュ |
| 座標の精度差 | 「町丁目レベル」 と「番地レベル」 の混在 | 精度レベルを記録、 解析時に考慮 |
| 離島・海上座標 | 住所不明な地点に「海の上」 の座標が返る | 都道府県境界ポリゴンで検証 |
| 外国住所の混入 | 「東京 → Tokyo, Japan」 で座標が異なる | 事前に言語・国別フィルタリング |
ジオコーディングの結果を rev_geocode で逆変換し、 入力住所と一致するかを確認するのが最も確実な品質検証法。 また、 都道府県境界ポリゴンに座標が含まれるかを確認することで、 大規模な誤りを発見できる。 これらは geopandas と shapely で簡単に実装できる。
以下の問いを通じて、 ジオコーディングの理解度を確認しましょう。
| # | 問い | 解答の方向性 |
|---|---|---|
| 1 | 「東京都千代田区永田町1-7-1」 と「東京都千代田区永田町一丁目7番1号」 をジオコーディングしたら、 異なる座標が返った。 原因と対処は? | 住所表記揺らぎ。 正規化前処理で半角/全角・漢数字/算用数字を統一する。 Nominatim 等の API では揺らぎに弱いことが多い。 |
| 2 | SSDSE-B-2026 の都道府県データを地図化したい。 住所文字列はないが県名はある。 どうする? | 都道府県名はジオコーディングの対象になるが、 むしろ JIS X 0401 都道府県コード経由で国土数値情報の境界ポリゴンと結合するのが速く正確。 |
| 3 | 10 万件の住所を一括ジオコーディングしたい。 Google Geocoding API を使うコストは? | 10 万 req × 0.005 USD/req = 500 USD。 月 200 USD 無料枠を引いて約 300 USD。 OpenStreetMap Nominatim なら自前サーバで無料だが、 精度に注意。 |
| 4 | ジオコーディング結果の座標が「海の上」 になっていた。 何が起きたか? | 住所がジオコードできず、 都道府県中心または海岸線近くの座標がフォールバックで返った可能性。 精度レベル (rooftop / approximate / city center 等) を必ず確認する。 |
| 5 | 「中央区銀座」 が大阪市の中央区にジオコードされた。 なぜか? | 都道府県名が省略されると、 API が文脈推測で誤る場合がある。 必ず都道府県を明示する (「東京都中央区銀座」)。 |
| 6 | 市町村合併で消えた地名 (例:「旧・北九州市門司区」) はどうジオコードする? | 合併履歴データベース (e-Stat や国勢調査の都道府県別データ) で新地名に変換してから API に投入。 |
| 7 | 逆ジオコード (緯度経度 → 住所) はどう使う? | (1) ジオコーディング結果の品質検証 (入力住所と逆変換結果が一致するか)、 (2) GPS データの住所表示、 (3) IP アドレスから推定した位置の地理的解釈。 |
| 8 | SSDSE-B-2026 と緯度経度マスタを結合する最良の方法は? | 都道府県コード (JIS X 0401) で内部結合 (INNER JOIN)。 SSDSE は 47 行で、 緯度経度マスタも 47 行が用意できるので、 1:1 結合になる。 |
これら 8 つの問いに自信を持って答えられれば、 ジオコーディングの基本は習得できている。 さらに深く学ぶには、 国土地理院の「電子国土基本図」 や OpenStreetMap の API ドキュメントを読み、 実際の住所データで試行錯誤するのが最良。 ジオコーディングは「地理空間情報の世界への入口」 で、 ここを越えれば GIS・空間統計・地理空間機械学習という広大な分野が開ける。
ジオコーディングを核として、 関連トピックへ広げていく学習経路を示す。 まず 可視化 で地図プロットの基礎を学び、 データ結合 で都道府県マスタとの結合を実践、 リレーショナルデータベース で空間データの保管方法を理解、 API でジオコーディング API の使い方を習得、 JSON で API レスポンスの解釈を学ぶ。 これらを順に身につけることで、 「住所文字列 → 緯度経度 → 地図表示 → 統計分析」 の一連のワークフローが完成する。 SSDSE-B-2026 を題材に、 47 都道府県の地理的特性を可視化・統計化することから、 ジオコーディング学習の最初の一歩を踏み出してほしい。
発展学習として、 (1) PostGIS による空間データベース、 (2) GeoPandas による空間データフレーム、 (3) Folium・Plotly Map による対話的地図、 (4) 空間自己相関 (Moran's I, Geary's C) による空間統計、 (5) クリギング (Kriging) による空間補間、 (6) 地理加重回帰 (GWR) による空間異質性のモデル化、 (7) リモートセンシングデータ (衛星画像) との統合、 を順に学ぶことで、 地理空間データサイエンスの全領域を制覇できる。 SSDSE-B-2026 のような都道府県単位データは、 こうした学習の出発点として最適で、 規模が小さい (47 行) ので試行錯誤が容易、 公的データなので信頼性も保証されている。
ジオコーディングの結果は緯度経度で返されるが、 地図上で表示・計算するには「座標系」 と「投影法」 の理解が必須。 最頻使用の座標系は WGS84 (EPSG:4326) で、 Google Maps, OpenStreetMap, GPS が共通で使用する。 日本国内では JGD2011 (EPSG:6668) が公式で、 国土地理院・国土数値情報が採用。 これら 2 つは緯度経度の精度に数メートルの差があり、 厳密な測量ではこの差を意識する必要がある。 投影法は「球面の地球を平面に描く方法」 で、 メルカトル図法 (世界地図)、 横メルカトル (UTM, JGD 系)、 ガウス・クリューゲル (日本の平面直角座標系) 等が代表的。 投影法を変えると距離・面積の計算結果が変わるため、 用途に応じて選択する必要がある。
Python の pyproj ライブラリで座標系変換が可能で、 from pyproj import Transformer; t = Transformer.from_crs(4326, 6668); t.transform(lat, lon) で WGS84 から JGD2011 への変換ができる。 GeoPandas では gdf.to_crs(epsg=6668) で一括変換可能。 SSDSE-B-2026 の都道府県データをジオコーディングして地図化する場合、 WGS84 のまま Folium 等で表示するのが手軽。 厳密な距離計算 (例: 都道府県間の最短距離) では UTM 等の投影座標に変換してからユークリッド距離を取るのが正確。 こうした座標系の扱いは、 地理情報を扱う際の基礎中の基礎で、 GIS エンジニアの必須スキル。
ジオコーディングで得た座標を、 SSDSE-B-2026 の都道府県別統計と組み合わせることで、 多様な空間統計分析が可能になる。 (1) 空間相関分析: 「人口密度の高い県は隣接県も人口密度が高いか」 を Moran's I で定量化。 (2) 空間クラスタ分析: 「経済力の高い県が地理的に集中しているか」 を Local Moran's I (LISA) で可視化。 (3) 空間補間: 一部県のデータから全国の値を推定する Kriging。 (4) 地理加重回帰 (GWR): 「人口と GDP の関係が地域によってどう違うか」 を地理的に変動する係数で表現。 (5) 空間自己回帰モデル (SAR): 隣接地域の効果を回帰に組み込む。 これらは古典的な OLS では捉えられない地理的構造を、 統計的に明示化する手法。
Python では PySAL (Python Spatial Analysis Library) が空間統計の総合ライブラリで、 libpysal, esda, spreg, splot 等のサブパッケージが提供されている。 SSDSE-B-2026 と国土数値情報の都道府県境界ポリゴンを組み合わせれば、 「人口密度の Moran's I」「経済力の LISA」「人口と GDP の GWR」 等の本格的空間統計分析が可能。 こうした分析は単純な OLS や相関より深い洞察を与え、 都道府県の地理的特性を踏まえた政策議論の基礎データになる。 SSDSE のジオコーディング応用は、 単に地図にプロットするだけでなく、 「地理が統計に与える影響」 を明示化する強力なツール。
ジオコーディングは「住所文字列を緯度経度に変換する」 単純な処理だが、 実務では住所表記揺らぎ・市町村合併・座標系の選択・API のコスト等、 多数の論点を含む。 SSDSE-B-2026 のような都道府県単位データでは、 都道府県コード経由で境界ポリゴンと結合するのが最も確実。 個別住所のジオコーディングには Google や HEREMaps の有料 API、 大規模利用には OpenStreetMap Nominatim の自前運用、 日本国内には国土地理院・国土数値情報、 という選択肢を用途に応じて使い分ける。 座標系 (WGS84, JGD2011) と投影法 (UTM, メルカトル) の理解が、 厳密な空間計算の基礎。 ジオコーディング結果と統計データを組み合わせることで、 空間相関・空間クラスタ・空間補間・GWR 等の高度な空間統計分析が可能になり、 「地理が統計に与える影響」 を定量化できる。 SSDSE のような小データから始めて、 PostGIS・GeoPandas・PySAL へと知識を広げることで、 地理空間データサイエンスの全領域が制覇できる。
ジオコーディング精度と利用可能性は国・地域で大きく異なる。 日本は世界でも最も住所体系が整備された国の一つで、 国土地理院や国土数値情報による公的データの精度が極めて高い。 米国は GPS と Census TIGER データにより、 番地レベルでの精度が確保されている。 欧州では国別に多様で、 ドイツ・オランダは整備度が高い一方、 地中海諸国では精度が低い地域もある。 中国・インド等の発展途上国では、 急速な都市化に住所体系が追いついておらず、 ジオコーディング精度が大きな課題。 アフリカ諸国では「住所が存在しない」 地域も多く、 What3words 等の代替方法が登場している。
こうした国・地域差は、 国際比較研究を行う際に大きな注意点となる。 例えば「世界の都市の人口密度」 を地理的にマッピングする場合、 国別にジオコーディング精度が異なるため、 結果の比較可能性が低下する。 SSDSE-B-2026 のような日本国内データでは精度が高く問題ないが、 国際展開する分析では「データ源の精度差」 を意識する必要がある。 グローバル展開する企業のロケーション分析、 国際機関の開発援助プロジェクト、 学術研究の国際比較等で、 こうした地域差を踏まえた設計が品質を決定する。
| 段階 | 習得内容 | SSDSE-B-2026 での実装課題 |
|---|---|---|
| 初級 | API の基本 (Google/Nominatim 呼び出し) | 47 都道府県の県庁所在地をジオコード |
| 初級 | 緯度経度の散布図表示 (matplotlib) | 47 県を地図上にプロット |
| 中級 | GeoJSON / Shapefile の読込 (geopandas) | 都道府県境界ポリゴンを表示 |
| 中級 | コロプレス図 (色塗り地図) | 人口密度を色で表現 |
| 中級 | Folium による対話的地図 | クリックで詳細表示 |
| 上級 | 座標系変換 (pyproj) | WGS84 と JGD2011 の変換 |
| 上級 | 空間自己相関 (Moran's I, PySAL) | 人口密度の空間構造を定量化 |
| 上級 | 空間補間 (Kriging, scikit-gstat) | 欠損県の値を推定 |
| 専門 | 地理加重回帰 (GWR) | 都道府県別の回帰係数を推定 |
| 専門 | リモートセンシング統合 | 衛星画像と統計データを組み合わせる |
→ このロードマップに沿って学習することで、 「住所変換」 から「空間データサイエンス」 へと段階的に視野を広げられる。 SSDSE-B-2026 は 47 行で扱いやすく、 各段階の演習に最適なサンプルサイズ。 教育機関でのカリキュラム設計でも、 SSDSE を題材とした「ジオコーディング → 地図化 → 空間統計 → 空間機械学習」 という流れが、 効果的な学習経路として推奨できる。
2026 年現在のジオコーディング最新動向として、 (1) LLM ベースのジオコーディング: GPT-4 や Claude に住所を渡すと、 文脈理解で曖昧な住所も解釈できる。 「東京駅近く」 のような曖昧表現でも適切な座標を返す。 (2) 衛星画像 + ストリートビューによる住所推定: 緯度経度から住所を推定する逆ジオコーディングの精度が、 画像認識との組合せで飛躍的に向上。 (3) IoT デバイスの自動ジオコーディング: スマートフォン・車載 GPS・スマートホーム機器が、 ユーザの行動を自動的に住所レベルでログ化。 (4) Privacy-Preserving Geocoding: 個人の位置情報を匿名化しつつ統計分析を可能にする技術 (差分プライバシ、 k-匿名化)。 (5) リアルタイム交通最適化: ジオコーディング + 交通ログ + 機械学習で、 動的な経路案内・渋滞予測が高度化。
これらの最新動向は、 SSDSE-B-2026 のような集計済み統計データを扱う場面では直接関わらないが、 業務や研究の最前線では日常的な技術。 学生諸氏が SSDSE で空間データ分析の基礎を学んだ後、 これらの最新技術に触れることで、 ジオコーディングが「単純な住所変換」 から「人間の行動を地理空間で理解する基盤」 へと進化していることを実感できる。 ジオコーディングは静かに進化を続けており、 公的統計とリアルタイム位置情報を統合した分析が、 政策決定・都市計画・防災・マーケティング等の幅広い分野で活用される時代になっている。 SSDSE-B-2026 を題材としたジオコーディング学習は、 そうした時代を生きる学生諸氏が、 地理空間データの世界に足を踏み入れる最初の扉となる。 47 都道府県という小さなデータセットから始まる学びの旅が、 やがてグローバルな地理空間データサイエンスの世界へと広がっていく、 その出発点としての価値を、 本ページの学習者に感じてもらえれば幸いである。 統計データ分析コンペティションは、 こうした地理空間データを実践的に扱う格好の機会で、 SSDSE と地理空間情報を組み合わせた分析を経験することで、 将来の業務・研究で広く生きる基礎力が養われる。 ジオコーディングは「住所と座標を結ぶ橋」 であり、 これを使いこなすことで、 政策・経済・社会・環境の様々なテーマが地理空間の視点から再解釈できる。 学生諸氏が SSDSE-B-2026 を通じてジオコーディングの基礎を体得し、 将来の研究・実務であらゆる地理空間データに自信を持って取り組めるようになることが、 本ページの究極的な学習目標である。 そのための地道な努力を、 焦らず着実に続けていってほしい。
🍰 まずはやさしく
場所を計算するための共通のルールです。
2つの地点の距離を出すために使います。
最寄り駅までの道のりを計算するときです。
距離を出す公式や便利な道具について読みます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 | # ── この抜粋で使う座標表をここで用意します ── # 都道府県庁所在地の座標 (緯度, 経度) -- 国土地理院公開データから抜粋 PREF_COORDS = { '北海道':(43.064,141.347),'青森県':(40.825,140.74),'岩手県':(39.704,141.153), '宮城県':(38.269,140.872),'秋田県':(39.719,140.103),'山形県':(38.241,140.364), '福島県':(37.75,140.468),'茨城県':(36.342,140.447),'栃木県':(36.566,139.884), '群馬県':(36.391,139.061),'埼玉県':(35.857,139.649),'千葉県':(35.605,140.123), '東京都':(35.69,139.692),'神奈川県':(35.448,139.643),'新潟県':(37.902,139.024), '富山県':(36.695,137.211),'石川県':(36.595,136.626),'福井県':(36.065,136.222), '山梨県':(35.664,138.568),'長野県':(36.651,138.181),'岐阜県':(35.391,136.722), '静岡県':(34.977,138.383),'愛知県':(35.180,136.907),'三重県':(34.730,136.509), '滋賀県':(35.005,135.869),'京都府':(35.022,135.756),'大阪府':(34.687,135.520), '兵庫県':(34.691,135.183),'奈良県':(34.685,135.833),'和歌山県':(34.226,135.168), '鳥取県':(35.504,134.238),'島根県':(35.472,133.051),'岡山県':(34.662,133.935), '広島県':(34.397,132.460),'山口県':(34.186,131.471),'徳島県':(34.066,134.559), '香川県':(34.34,134.043),'愛媛県':(33.842,132.766),'高知県':(33.560,133.531), '福岡県':(33.607,130.418),'佐賀県':(33.249,130.299),'長崎県':(32.745,129.874), '熊本県':(32.79,130.742),'大分県':(33.238,131.613),'宮崎県':(31.911,131.424), '鹿児島県':(31.560,130.558),'沖縄県':(26.213,127.681), } from math import radians, sin, cos, sqrt, asin def haversine(p1, p2): R = 6371.0 lat1, lon1 = map(radians, p1) lat2, lon2 = map(radians, p2) dlat = lat2 - lat1; dlon = lon2 - lon1 a = sin(dlat/2)**2 + cos(lat1)*cos(lat2)*sin(dlon/2)**2 return 2 * R * asin(sqrt(a)) # 47都道府県の総当たり距離行列 import pandas as pd pref_list = list(PREF_COORDS.keys()) mat = pd.DataFrame(index=pref_list, columns=pref_list, dtype=float) for p1 in pref_list: for p2 in pref_list: mat.loc[p1,p2] = haversine(PREF_COORDS[p1], PREF_COORDS[p2]) # 最遠ペア import numpy as np idx = np.unravel_index(mat.values.argmax(), mat.shape) print(f'最遠: {pref_list[idx[0]]} - {pref_list[idx[1]]}: {mat.values.max():.1f} km') |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 | import pandas as pd # 都道府県の代表点。あとのブロックでも同じ表を使う pref_coords = { '北海道':(43.064,141.347),'青森県':(40.825,140.74),'岩手県':(39.704,141.153), '宮城県':(38.269,140.872),'秋田県':(39.719,140.103),'山形県':(38.241,140.364), '福島県':(37.75,140.468),'茨城県':(36.342,140.447),'栃木県':(36.566,139.884), '群馬県':(36.391,139.061),'埼玉県':(35.857,139.649),'千葉県':(35.605,140.123), '東京都':(35.69,139.692),'神奈川県':(35.448,139.643),'新潟県':(37.902,139.024), '富山県':(36.695,137.211),'石川県':(36.595,136.626),'福井県':(36.065,136.222), '山梨県':(35.664,138.568),'長野県':(36.651,138.181),'岐阜県':(35.391,136.722), '静岡県':(34.977,138.383),'愛知県':(35.180,136.907),'三重県':(34.730,136.509), '滋賀県':(35.005,135.869),'京都府':(35.022,135.756),'大阪府':(34.687,135.520), '兵庫県':(34.691,135.183),'奈良県':(34.685,135.833),'和歌山県':(34.226,135.168), '鳥取県':(35.504,134.238),'島根県':(35.472,133.051),'岡山県':(34.662,133.935), '広島県':(34.397,132.460),'山口県':(34.186,131.471),'徳島県':(34.066,134.559), '香川県':(34.34,134.043),'愛媛県':(33.842,132.766),'高知県':(33.560,133.531), '福岡県':(33.607,130.418),'佐賀県':(33.249,130.299),'長崎県':(32.745,129.874), '熊本県':(32.79,130.742),'大分県':(33.238,131.613),'宮崎県':(31.911,131.424), '鹿児島県':(31.560,130.558),'沖縄県':(26.213,127.681), } df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', skiprows=1) df23 = df[df['年度'] == 2023].reset_index(drop=True) df23['lat'] = df23['都道府県'].map(lambda x: pref_coords[x][0]) df23['lon'] = df23['都道府県'].map(lambda x: pref_coords[x][1]) w = df23['総人口'] center_lat = (df23['lat'] * w).sum() / w.sum() center_lon = (df23['lon'] * w).sum() / w.sum() print(f'人口加重中心: ({center_lat:.4f}, {center_lon:.4f})') # おおむね岐阜県あたり (関東に人口偏在で東寄り) |
| やりたいこと | 使うもの |
|---|---|
| 住所→座標 | GSI API, geopy, Google Maps |
| 座標→住所 (逆) | Reverse Geocoding API |
| 住所正規化 | unicodedata.normalize('NFKC'), 自前正規表現 |
| 距離計算 | Haversine 公式 or geopy.distance |
| 測地系変換 | pyproj.Transformer |
| 地図表示 (静止) | GeoPandas + matplotlib |
| 地図表示 (Web) | folium, leaflet, kepler.gl |
| 空間結合 | gpd.sjoin (PointInPolygon) |
| 経路探索 | OSRM, OpenRouteService |
| 大量バッチ | 国土地理院 街区位置参照情報 + ローカルDB |
公的統計データを地図化することで、 数字の羅列が「地理的パターン」 として見えてきます。 「東京一極集中」「西高東低」「沖縄の若さ」など、 数値表だけでは伝わらない含意が地図には宿ります。
| 層 | 代表ツール | 役割 |
|---|---|---|
| ジオコーディング | GSI API, geopy, Nominatim | 住所⇔座標 |
| 地理データ形式 | Shapefile, GeoJSON, GPKG, KML | 境界・点線面の保存 |
| 分析ライブラリ | GeoPandas, Shapely, pyproj | Python での空間演算 |
| 可視化 (静止) | matplotlib, plotnine, contextily | 論文・報告書用 |
| 可視化 (Web) | folium, leaflet.js, mapbox, kepler.gl | インタラクティブ |
| デスクトップ GIS | QGIS (無料), ArcGIS Pro (有料) | プロ用の総合 GIS |
| DB | PostGIS, SpatiaLite, BigQuery GIS | 空間 SQL |
| 経路探索 | OSRM, OpenRouteService, Valhalla | ナビゲーション |
| リモートセンシング | rasterio, xarray, GDAL | 衛星画像処理 |
| 公的データソース | 国土地理院, 国土数値情報, e-Stat 地域メッシュ | 無料で取得可能 |
Haversine 公式は 2 点 $(\phi_1, \lambda_1)$ と $(\phi_2, \lambda_2)$ の球面距離を:$$d = 2R \arcsin\sqrt{\sin^2\!\left(\frac{\Delta\phi}{2}\right) + \cos\phi_1\cos\phi_2\sin^2\!\left(\frac{\Delta\lambda}{2}\right)}$$ と計算します。 $R$ = 地球の平均半径 (6371 km)。 直線距離 (大圏距離) で、 平面ユークリッドより数学的に正確。 47 都道府県の県庁所在地ペアの距離は、 この公式で計算すると最遠が札幌-那覇で約 2200 km、 最近が東京-横浜で約 30 km です。
より高精度な楕円体距離は Vincenty 公式や Karney (2013) のアルゴリズムを使います。 pyproj.Geod.inv() で簡単に呼べます。 短距離 (数 km) なら Haversine で十分、 長距離・高精度なら Vincenty、 と覚えればOK。
ジオコーディングは一見シンプルですが、 完全な精度は原理的に困難です。 第一の理由は住所の曖昧性: 同じ住所が複数の建物を指す、 番地が連続せず飛ぶ、 「○○丁目」 と 「丁目」 なしの混在など、 ルールベースの正規化で吸収しきれないケースが残ります。 第二の理由は動的な変更: 区画整理・市町村合併・新規住居表示で住所体系が変わるため、 過去の住所が「現在」 のジオコーディングデータベースにヒットしないことがあります。
そのため、 大規模な実務システムでは「マッチ率 95% 以上」 を目標としつつ、 残り 5% は手作業で対応するのが現実解です。 機械学習でファジーマッチを行う研究もあり、 編集距離 + N-gram + 学習済みエンコーダ (BERT 系) の組み合わせで 99% に迫る精度を出すケースも出てきています。
SSDSE-B-2026 のような都道府県レベルなら完全な対応が可能ですが、 住所→緯度経度の世界に入ると「完璧は存在しない」 ことを意識しておくと、 失敗時の対処が冷静にできます。
| サービス | コスト | 精度 | 利用規約上の注意 |
|---|---|---|---|
| Google Geocoding API | 従量課金 | ◎ | 地図表示と組み合わせ必須 |
| Mapbox | 従量課金 | ○ | 商用OK |
| 国土地理院 | 無料 | ○ 日本特化 | 商用OK・出典明記 |
| OpenStreetMap (Nominatim) | 無料(共有) | △ | 負荷制限あり、 商用は自前ホスト |
| jageocoder (Python) | 無料・オフライン | ○ 日本特化 | パッケージ単独で動作 |
点(緯度経度)が含まれるポリゴン(都道府県)を判定する操作。 geopandas の sjoin で実装。 SSDSE-B-2026 の市町村別データを使えば、 GPS ログから滞在都道府県を集計できる。
ジオコーディング (Geocoding) は「住所文字列 → 緯度経度の数値ペア」 への写像です。 数学的には次のように定式化できます:$$g: \mathcal{S} \to \mathbb{R}^2 \cup \{\bot\}, \quad g(\text{address}) = (\phi, \lambda)$$ ここで $\mathcal{S}$ は住所文字列の集合 ("東京都千代田区千代田1-1" など)、 $(\phi, \lambda)$ は緯度・経度のペア、 $\bot$ は「変換失敗」を表す特殊値です。 この写像は多対一(同じ場所を指す複数の住所表記が同じ座標になる)でかつ非決定的(建物の重心か入口かで座標が変わる)であり、 完全な逆写像は存在しません。
入力となる住所文字列は、 日本では「都道府県 + 市区町村 + 字・町丁目 + 番地」の階層構造を持ちます (例: 東京都千代田区千代田1-1-1)。 ただし、 実データには「〒100-0001」郵便番号付きや「東京都千代田区千代田一丁目1-1」 漢数字版、 「東京都 千代田区 千代田1-1」 全半角空白混在、 「千代田1-1-1 千代田区」 のような順序違いなど、 表記揺れが膨大です。 正規化(normalization)がジオコーディングの前段で最も重要な工程で、 全角→半角、 漢数字→アラビア数字、 「丁目」 削除、 旧字体→新字体などの変換を行います。 SSDSE-B-2026 の都道府県コード (R01000-R47000) と都道府県名 (北海道〜沖縄県) は単純な対応関係ですが、 これは「都道府県レベルの最も粗いジオコーディング」と言えます。
変換アルゴリズム $g$ は内部に巨大な住所データベースを持ちます。 国土地理院の「街区レベル位置参照情報」「大字・町丁目レベル位置参照情報」 が国内の代表的データソースで、 約 26 万町丁目 × 1500 万街区の座標を持ちます。 与えられた住所文字列を正規化した後、 トライ木や Elasticsearch のような全文検索インデックスでマッチング、 最も近い既知住所の座標を返す、 という流れです。 商用 API (Google Maps Geocoding、 GSI(Geospatial Information Authority of Japan)等) は数十億の住所をカバーし、 高精度を提供します。 オープンソースだと Nominatim (OpenStreetMap ベース) が主要選択肢。
出力は緯度 $\phi$ (latitude, 南北方向、 -90〜+90 度)、 経度 $\lambda$ (longitude, 東西方向、 -180〜+180 度) のペア。 日本国内なら $\phi \in [24, 46]$、 $\lambda \in [122, 154]$ の範囲。 重要な点は測地系 (Geodetic Datum) の違いで、 日本では「日本測地系 (Tokyo Datum)」 (旧) と 「世界測地系 (JGD2000 / JGD2011)」 (現行) があり、 同じ住所でも 400-500m ずれます。 GPS / Web 地図は世界測地系を使うので、 古いデータを使うときは要注意。 SSDSE-B 自体には座標列はありませんが、 都道府県別データを地図にプロットするときは、 まず都道府県庁所在地の座標 (緯度経度) を別途取得して結合します。
$g$ は完全関数ではありません。 入力住所が存在しない (誤入力)、 表記揺れがマッチしない、 新住所がデータベース未収録、 ビル名のみ (番地不明) などの場合、 $g$ は $\bot$ (失敗) を返します。 実務では「マッチ率」 (= 全レコードのうち成功したジオコーディング数 / 全件) が重要な指標で、 90-95% を超えるのが望ましいとされます。 マッチ失敗時の対処として、 (1) 階層的フォールバック (番地→丁目→市区町村レベルへ後退)、 (2) ファジーマッチ (編集距離での近似マッチ)、 (3) 人手レビュー、 のいずれかを取ります。 また、 同じ住所でも複数の座標候補が返る (建物の重心 vs 入口 vs 駐車場) ことがあり、 用途に応じて選択が必要です。
3 次元の球面を 2 次元の地図に変換する「投影法 (projection)」 は地理学の核心テーマです。 用途に応じて選ぶ必要があります:
| 投影法 | EPSG | 特徴 | 用途 |
|---|---|---|---|
| Web Mercator | 3857 | 高緯度が大きく見える | Web 地図 (Google, OSM) |
| WGS84 (経緯度) | 4326 | GPS 標準 | 座標保存 |
| JGD2011 | 6668 | 日本国内向け | 公的地理データ |
| 平面直角座標系 | 6669-6687 | 日本を19区分 | 測量・都市計画 |
| UTM Zone 53 | 32653 | 日本中部・東部 | 国際標準 |
| Albers 等積 | 独自定義 | 面積を保つ | 統計地図 |
SSDSE-B のような統計地図には Albers 等積投影が理想ですが、 Web 表示なら Web Mercator (3857) で十分。 pyproj で簡単に切り替え可能。
SSDSE 47 都道府県の県庁所在地に緯度経度を付与する例:
| 都道府県 | 県庁所在地 | 緯度 | 経度 |
|---|---|---|---|
| 北海道 | 札幌市 | 43.06 | 141.35 |
| 東京都 | 新宿区 | 35.69 | 139.69 |
| 沖縄県 | 那覇市 | 26.21 | 127.68 |
SSDSE-B-2026 の都道府県名を国土交通省提供の都道府県界 GeoJSON とジオコーディングで結びつけ、 高齢化率のコロプレス地図を描く。
| 要素 | 具体 | SSDSE-B での使い方 |
|---|---|---|
| ジオコーディング | 住所→緯度経度 | 地域コード(R01000 等)と GeoJSON のキーを突合 |
| 逆ジオコーディング | 緯度経度→住所 | GPS ログ→都道府県の集計 |
| シェイプファイル | .shp 形式の境界 | GADM, 国土数値情報 |
| GeoJSON | JSON ベース地理 | Web 描画用 |
| MVT | ベクトルタイル | Mapbox/MapLibre |
data/raw/ に置くと、そのまま動きます。japan_prefectures.geojson(都道府県の境界)… https://raw.githubusercontent.com/dataofjapan/land/master/japan.geojsonを保存して使えます(列名は nam_ja)。N03-23_230101.shp(市区町村の境界)… 国土交通省「国土数値情報 行政区域データ」https://nlftp.mlit.go.jp/ksj/ から年度を選んでダウンロードします。1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | # SSDSE-B-2026 で都道府県別高齢化率を地図化
import pandas as pd
import geopandas as gpd
import folium
# 1. SSDSE-B 読み込み
df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', skiprows=1)
df = df[df['年度']==2023].copy()
df['高齢化率'] = df['65歳以上人口']/df['総人口']*100
# 2. 都道府県境界 GeoJSON (例: 国土数値情報)
geo = gpd.read_file('data/raw/japan_prefectures.geojson')
# 3. 結合
merged = geo.merge(df[['都道府県','高齢化率']],
left_on='nam_ja', right_on='都道府県')
# 4. 地図化
m = folium.Map(location=[36, 138], zoom_start=5)
folium.Choropleth(
geo_data=merged.__geo_interface__,
data=merged, columns=['nam_ja','高齢化率'],
key_on='feature.properties.nam_ja',
fill_color='YlOrRd', fill_opacity=0.7,
legend_name='高齢化率 (%)',
).add_to(m)
m.save('aged_ratio_map.html')
# 上位5県: 秋田(38.6), 高知(36.1), 山口(35.2), 徳島(34.7), 山形(34.6)
print(df.nlargest(5,'高齢化率')[['都道府県','高齢化率']])
|
data/raw/SSDSE-B-2026.csv + 都道府県庁所在地の座標 (47 件の辞書 or CSV)。1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 | import os os.makedirs('outputs', exist_ok=True) # 保存先のフォルダを作っておく import pandas as pd import matplotlib.pyplot as plt # 都道府県庁所在地の座標 (緯度, 経度) -- 国土地理院公開データから抜粋 pref_coords = { '北海道':(43.064,141.347),'青森県':(40.825,140.74),'岩手県':(39.704,141.153), '宮城県':(38.269,140.872),'秋田県':(39.719,140.103),'山形県':(38.241,140.364), '福島県':(37.75,140.468),'茨城県':(36.342,140.447),'栃木県':(36.566,139.884), '群馬県':(36.391,139.061),'埼玉県':(35.857,139.649),'千葉県':(35.605,140.123), '東京都':(35.69,139.692),'神奈川県':(35.448,139.643),'新潟県':(37.902,139.024), '富山県':(36.695,137.211),'石川県':(36.595,136.626),'福井県':(36.065,136.222), '山梨県':(35.664,138.568),'長野県':(36.651,138.181),'岐阜県':(35.391,136.722), '静岡県':(34.977,138.383),'愛知県':(35.180,136.907),'三重県':(34.730,136.509), '滋賀県':(35.005,135.869),'京都府':(35.022,135.756),'大阪府':(34.687,135.520), '兵庫県':(34.691,135.183),'奈良県':(34.685,135.833),'和歌山県':(34.226,135.168), '鳥取県':(35.504,134.238),'島根県':(35.472,133.051),'岡山県':(34.662,133.935), '広島県':(34.397,132.460),'山口県':(34.186,131.471),'徳島県':(34.066,134.559), '香川県':(34.34,134.043),'愛媛県':(33.842,132.766),'高知県':(33.560,133.531), '福岡県':(33.607,130.418),'佐賀県':(33.249,130.299),'長崎県':(32.745,129.874), '熊本県':(32.79,130.742),'大分県':(33.238,131.613),'宮崎県':(31.911,131.424), '鹿児島県':(31.560,130.558),'沖縄県':(26.213,127.681), } df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', skiprows=1) df23 = df[df['年度']==2023].copy() df23['lat'] = df23['都道府県'].map(lambda x: pref_coords[x][0]) df23['lon'] = df23['都道府県'].map(lambda x: pref_coords[x][1]) # 散布マップを描画 plt.figure(figsize=(8,8)) plt.scatter(df23['lon'], df23['lat'], s=df23['総人口']/2e4, alpha=0.6, c=df23['総人口'], cmap='YlOrRd') plt.colorbar(label='総人口') for _, r in df23.iterrows(): plt.annotate(r['都道府県'][:2], (r['lon'], r['lat']), fontsize=7) plt.xlabel('経度'); plt.ylabel('緯度') plt.title('SSDSE-B-2026 (2023年) 都道府県の人口分布') plt.tight_layout(); plt.savefig('outputs/japan_population.png', dpi=120) |
| 業界 | ジオコーディングの役割 | 代表ツール |
|---|---|---|
| EC・物流 | 注文住所を座標化し、 最寄り倉庫を判定、 配送ルート最適化。 Uber / 出前館 / ヤマトの中核機能。 | Google Maps API, OSRM |
| 不動産 | 物件住所 → 座標 → 地図表示。 駅徒歩距離計算、 周辺施設検索。 SUUMO / アットホームの基本機能。 | GSI Geocode, OpenCage |
| 公衆衛生 | 感染症の患者住所 → 座標 → ヒートマップ。 COVID 期は厚労省・各自治体が大規模実施。 | QGIS, ArcGIS, GeoPandas |
| 保険・金融 | 契約者住所 → ハザードマップ重ね → 火災・水害リスク評価 → 保険料計算。 | GIS + 国土地理院データ |
| マーケティング | 店舗顧客住所 → 商圏分析 → 新規出店適地評価。 コンビニ・スーパーの出店戦略。 | Tableau, GeoPandas |
| 公的統計 | SSDSE 系の都道府県データを地図化。 自治体オープンデータの活用基盤。 | GeoPandas + folium |
| API | 日本住所 | 精度 | 料金 | 利用制限 |
|---|---|---|---|---|
| Google Maps Geocoding | ◎ | 最高 | 5 USD/1000 req | キャッシュ禁止 |
| GSI (国土地理院) | ◎ | 高 | 無料 | 利用規約あり |
| Yahoo! Geocoder | ○ | 高 | 無料 (制限あり) | 50000/日 |
| OpenCage | ○ | 中 | 低価格 | 無料枠あり |
| Nominatim (OSM) | △ | 中 | 無料 | 1 req/s |
| geocoder.us | × | 米国専用 | - | - |
| Mapbox Geocoding | △ | 中 | 0.75 USD/1000 | 無料枠 |
| CSIS (東大空間情報) | ◎ | 高 | 無料 (研究用) | アカデミック |
日本測地系 (Tokyo Datum) と世界測地系 (JGD2000) を混在させると、 同じ住所でも 400-500m ずれる。 古い住宅地図と Google Maps を重ねると地震が起きたみたいに見える。 対策: 全データを世界測地系に統一する。 pyproj で変換。
「東京都千代田区」 と 「東京都 千代田区」 (全角空白) が別住所扱いになり、 半分のレコードがジオコード失敗。 対策: 正規化 (NFKC 正規化、 unicodedata.normalize('NFKC', s)) を必須前処理に。
町村合併で消滅した「○○郡△△町」 をジオコードすると失敗。 対策: 住所変更履歴のテーブルを別途持ち、 fallback で新住所に置換してから再試行。
100 万件の住所を Google Maps API で逐次ジオコードして、 数日かかり料金 5000 ドル超え。 対策: ローカルにジオコーディングDB (Nominatim) を立てるか、 国土地理院の街区レベル位置参照情報をバッチで使う。
Google Maps の結果を 30 日以上キャッシュすると規約違反。 法務リスク。 対策: 規約をよく読む、 オープンデータ系 (GSI、 OSM) を使う。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | import requests, time def gsi_geocode(address): url = 'https://msearch.gsi.go.jp/address-search/AddressSearch' res = requests.get(url, params={'q': address}) data = res.json() if data: coords = data[0]['geometry']['coordinates'] return (coords[1], coords[0]) # (lat, lon) return None # 都道府県庁を一括ジオコード prefs = ['東京都千代田区千代田1-1','大阪府大阪市中央区大手前2','京都府京都市上京区'] results = [(p, gsi_geocode(p)) for p in prefs] for p, c in results: print(p, '->', c) time.sleep(0.5) # API レート制限を守る |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | import os os.makedirs('outputs', exist_ok=True) # 保存先のフォルダを作っておく import geopandas as gpd import pandas as pd # 国土数値情報の都道府県境界 Shapefile jp = gpd.read_file('data/raw/N03-23_230101.shp', encoding='utf-8') jp = jp.dissolve(by='N03_001') # 都道府県単位に集約 df23 = pd.read_csv(...) # SSDSE-B 2023年 merged = jp.merge(df23, left_on='N03_001', right_on='都道府県名') ax = merged.plot(column='総人口', cmap='YlOrRd', legend=True, edgecolor='gray', figsize=(10,12)) ax.set_title('SSDSE-B-2026 (2023) 都道府県別人口') ax.set_axis_off() plt.savefig('outputs/japan_choropleth.png', dpi=120) |
1 2 3 4 5 6 7 8 9 10 | import folium m = folium.Map(location=[36.0, 138.0], zoom_start=5, tiles='OpenStreetMap') for _, r in df23.iterrows(): folium.CircleMarker( location=[r['lat'], r['lon']], radius=r['総人口']/5e5, popup=f"{r['都道府県']}: {r['総人口']:,}人", color='red', fill=True, fill_opacity=0.5 ).add_to(m) m.save('outputs/japan_map.html') |
1 2 3 4 5 6 | from pyproj import Transformer # Tokyo Datum (EPSG:4301) → WGS84 (EPSG:4326) tf = Transformer.from_crs('EPSG:4301', 'EPSG:4326', always_xy=True) old_lon, old_lat = 139.7610, 35.6760 # 東京駅(古い座標) new_lon, new_lat = tf.transform(old_lon, old_lat) print(f'差: {(new_lat-old_lat)*111000:.1f}m') # 約400-500m |
1 2 3 4 5 6 7 8 9 10 11 | from math import radians, sin, cos, sqrt, asin def haversine(lat1, lon1, lat2, lon2): R = 6371 # 地球半径 km lat1, lon1, lat2, lon2 = map(radians, [lat1, lon1, lat2, lon2]) dlat = lat2 - lat1; dlon = lon2 - lon1 a = sin(dlat/2)**2 + cos(lat1)*cos(lat2)*sin(dlon/2)**2 return 2 * R * asin(sqrt(a)) # 東京-大阪の直線距離 d = haversine(35.69, 139.69, 34.69, 135.52) print(f'東京-大阪: {d:.1f} km') # 約 400km |
合成データで住所→緯度経度変換の成功率と誤差を計算する。
| 区分 | 件数 | 平均誤差 [m] |
|---|---|---|
| 正確 | 800 | 5 |
| 概略 | 150 | 50 |
| 失敗 | 50 | — |
合計 1,000 件
1 2 3 4 5 6 7 8 | import numpy as np n = np.array([800, 150, 50]) err = np.array([5, 50, np.nan]) total = n.sum() success = n[:2].sum() / total weighted_err = (n[:2] * err[:2]).sum() / n[:2].sum() print(f"成功率: {success:.2f}") print(f"加重平均誤差: {weighted_err:.1f} m") |
💬 手計算 (Step 2) 95% / 12.1m と Python 出力が完全一致。
🎯 このコードでやること: SSDSE-B-2026 の 47 都道府県の県庁所在地住所を geopy.Nominatim でジオコーディング (住所 → 緯度経度) し、 結果を pandas DataFrame に統合する。 さらに東京 (霞が関) からの距離を geopy.distance で計算して、 「人口と東京からの距離の相関」を見るところまで進める。
📥 入力データ (県庁所在地リスト、 公開資料より):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | # pip install geopy pandas import time import pandas as pd from geopy.geocoders import Nominatim from geopy.distance import geodesic geolocator = Nominatim(user_agent='ssdse-demo') addresses = { '北海道': '札幌市中央区北3条西6', '東京都': '新宿区西新宿2-8-1', '大阪府': '大阪市中央区大手前2', '沖縄県': '那覇市泉崎1-2-2', } rows = [] for pref, addr in addresses.items(): loc = geolocator.geocode(addr, timeout=10) rows.append((pref, loc.latitude, loc.longitude)) time.sleep(1) # Nominatim 利用規約: 1 req/s df = pd.DataFrame(rows, columns=['Prefecture', 'lat', 'lon']) tokyo = (35.6896, 139.6917) # 都庁 df['dist_km'] = df.apply( lambda r: geodesic((r.lat, r.lon), tokyo).kilometers, axis=1) print(df) |
📤 実行すると次の出力が得られる:
💬 結果の読み方: ジオコーディングで住所 → 緯度経度に変換できた。 東京都が距離 0、 大阪 396km、 札幌 832km、 那覇 1554km と地理的に妥当。 これを 47 都道府県に拡張し SSDSE-B の人口・出生数と JOIN すれば、 「東京からの距離と人口の負相関」「沖縄県のような外れ的県」を地理的視点で分析できる。 ⚠️ Nominatim は 1 req/s のレート制限あり、 大量処理は geocode.farm や Google Geocoding API 等を使う。
実際の API は一切呼ばず、 47 都道府県庁の公知座標(国土地理院公開の県庁所在地座標に基づく)を JavaScript 内の辞書として持たせた オフライン・ジオコーダ です。 ①「住所文字列 → (緯度, 経度)」の順変換、 ②表記揺れ(「東京」 vs 「東京都」)による失敗の再現、 ③地図クリック / タップによる逆ジオコーディング(座標 → 最寄り県庁)、 ④2 地点間の距離計算(ヒュベニの公式、 GRS80 楕円体)を体感できます。
x = (経度 − 最小経度) × cos(中央緯度) × 倍率、 y = (最大緯度 − 緯度) × 倍率 という線形写像(cos 補正付きの簡易正距円筒図法)。 経度に cos(緯度) を掛けるのは、 高緯度ほど経線間隔が狭まる歪みを軽減するため。geodesic)を使う。sjoin / sjoin_nearest で結合でき、 SSDSE の集計データと個票の橋渡しができる。
┌───────────────────┐
│ 位置情報の世界 │
└────────┬──────────┘
│
┌─────────────────┼─────────────────┐
▼ ▼ ▼
┌──────────┐ ┌──────────┐ ┌──────────┐
│ ジオコーディング │ │ リバースGC │ │ GIS分析 │
│ 住所→座標 │ │座標→住所 │ │空間演算 │
└────┬─────┘ └──────────┘ └──────────┘
│
┌─────────┼─────────┐
▼ ▼ ▼
┌────────┐ ┌──────┐ ┌──────────┐
│ 商用API │ │ 公的 │ │ ローカル │
│Google │ │ GSI │ │街区位置参照│
│Maps │ │CSIS │ │情報CSV │
└────────┘ └──────┘ └──────────┘
│
▼
┌─────────────────┐
│ 地図表示・空間分析 │
│ GeoPandas/folium │
│ QGIS/PostGIS │
└─────────────────┘
ジオコーディングは「データに位置情報を与える技術」 です。 表形式のデータを地図上にプロットするだけで、 数字の羅列が「物語」 に変わります。 47 都道府県の高齢化率を見るより、 地図上の色で見るほうが「東北・四国・中国地方の高齢化」 が直感的に分かる。 これがジオコーディング + GIS の力です。
SSDSE-B-2026 は座標を含みませんが、 都道府県庁所在地と組み合わせることで簡単に地図化できます。 そこから一歩進めば、 国土地理院の市区町村境界 Shapefile と組み合わせて「市区町村レベルでの細かい統計地図」 も作れます。 公的統計データを地理空間で見る習慣を持つと、 「数字に隠れていた地理パターン」 が見えてきます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | import geopandas as gpd jp = gpd.read_file('data/raw/N03-23_230101.shp').dissolve(by='N03_001') # 47x47 の隣接行列 neighbors = {} for i, row1 in jp.iterrows(): nb = [] for j, row2 in jp.iterrows(): if i != j and row1.geometry.touches(row2.geometry): nb.append(j) neighbors[i] = nb print('東京都の隣県:', neighbors['東京都']) # ['神奈川県', '埼玉県', '千葉県', '山梨県'] print('鳥取県の隣県:', neighbors['鳥取県']) # ['島根県', '岡山県', '広島県', '兵庫県'] |
1 2 3 4 5 6 7 8 | from pysal.lib import weights from pysal.explore.esda import Moran # 47県の隣接行列を pysal の重み行列に w = weights.Queen.from_dataframe(jp.reset_index()) mor = Moran(df23['高齢化率'].values, w) print(f"Moran's I = {mor.I:.3f}, p = {mor.p_norm:.4f}") # 正なら「高齢化率が高い県の隣も高い」(空間相関あり) |
1 2 3 4 5 | from keplergl import KeplerGl m = KeplerGl(height=800) m.add_data(data=df23, name='SSDSE-B-2023') m.save_to_html(file_name='outputs/japan_kepler.html') # 3Dヒストグラム、 アニメーション可能 |
1 2 3 4 5 6 7 | import requests # Tokyo → Osaka の道路距離 url = 'https://router.project-osrm.org/route/v1/driving/139.692,35.69;135.520,34.687' res = requests.get(url, params={'overview':'false'}).json() print(f"距離: {res['routes'][0]['distance']/1000:.1f} km") print(f"時間: {res['routes'][0]['duration']/60:.1f} 分") # 約 510 km, 6-7 時間 |
1 2 3 4 5 6 7 | # e-Stat の地域メッシュ (500m / 1km) 統計を取得 import requests url = 'https://api.e-stat.go.jp/rest/3.0/app/json/getStatsData' params = {'appId':'<APP_ID>','statsDataId':'<MESH_DATA_ID>'} data = requests.get(url, params=params).json() # 100m / 500m / 1km / 5km の標準地域メッシュ # 緯度経度を地域メッシュコードに変換するライブラリ jismesh-utils |
SSDSE-B は都道府県レベルだが、 e-Stat の小地域統計を併用すれば市区町村レベルの地図が作れる。
1 2 3 4 5 6 7 8 9 10 11 | import os os.makedirs('outputs', exist_ok=True) # 保存先のフォルダを作っておく import geopandas as gpd # 国土数値情報の N03 ファイル (市区町村境界) muni = gpd.read_file('data/raw/N03-23_230101.shp', encoding='utf-8') print(muni.head()) # 約 1700 市区町村のジオメトリ muni.plot(column='N03_007', cmap='tab20', figsize=(10,12), legend=False) plt.title('日本の市区町村境界') plt.savefig('outputs/japan_muni.png', dpi=120) |
SSDSE-B (47行) を市区町村レベル (1700行) に展開するには、 人口比で按分する近似手法もある (補間)。 厳密には市区町村単位のデータが必要。
マッピング・ジオコーディングは単独で完結せず、 上流の住所文字列正規化 (NEologd / 漢数字統一)、 並列の reverse geocoding と住所マッチング、 下流の地理可視化 (Folium / Plotly choropleth) や空間結合 (sjoin) と連動して初めて意味を持つ。
SSDSE-B-2026 の 47 都道府県データに緯度経度を付与したい場合、 上流で県名を国土地理院 API に投げて (35.6895, 139.6917) を取得、 中段で gpd.GeoDataFrame に変換、 下流で choropleth map で人口密度を色塗りする、 という典型フロー。
ジオコーディングの手法選択は、 (1) 精度要件 (県単位/市区町村単位/番地単位)、 (2) リクエスト数 (無料枠で済むか)、 (3) リアルタイム必要性、 で判定する。 県単位なら自作辞書、 番地単位なら Google Maps / Mapbox API。
実務では国土地理院 + Nominatim (OSM) を併用して矛盾を検出するのが安全で、 商用なら Google Maps の Geocoding API が住所揺れに最も強い。 SSDSE-B-2026 のような県単位データなら 50 行の辞書で十分。
このページの本文では「住所 → 緯度経度」 という変換を扱いました。 ここでは逆向きの見落としに注目します。 都道府県のような面(エリア)を地図に載せるとき、 私たちは無意識に「北海道 → 1つの点(県庁)」 のように面を1点へ畳み込む操作をしています。 この畳み込みは非可逆で、 「どの1点を代表にするか」 で分析結果が変わります。 姉妹ページ 地理的可視化 が「面をどう塗るか(面積バイアス)」 を扱うのに対し、 本節は「面をどう1点に潰すか」 という補完的な角度です。
Code 列が前計算済みのジオコード(キー)として機能します。 例:北海道 R01000/東京都 R13000/広島県 R34000/沖縄県 R47000(いずれも実測・B の 2023 行より)。Code(R01000 等)を結合キーにすれば、 「東京」/「東京都」 のような揺れの罠を回避できます。 実測で確認すると、 Code は 2023 年 47 行すべてで一意、 かつ北海道は 2012–2023 年を通して常に R01000 で不変でした。 つまり Code は「時間に対して安定したジオコード」 です。