Pythonで地理データをマッピング:小山市と栃木市を可視化する方法
地理空間データを使った分析や可視化は、データ分析スキルをさらに向上させる手段の一つです。この記事では、Pythonを使って、小山市と栃木市に関するデータを可視化する方法を解説します。作業はgoogleのcolabで実施しました。
使用したデータ
e-stat(政府統計の総合窓口)
国土数値情報(国土交通省)
------------------------------------
必要なライブラリ
以下のライブラリを使用します。事前にインストールしてください。
pip install geopandas pandas folium pyproj shapely
ステップ1:データの読み込み
Google Driveに保存されたデータを読み込みます。
from google.colab import drive
import geopandas as gpd
import pandas as pd
# Google Driveをマウント
drive.mount('/content/drive')
# ファイルパス設定
csv_path = '/path_to_population_data.csv'
shp_path = '/path_to_town_boundary.shp'
station_path = '/path_to_station_data.geojson'
land_price_path_1 = '/path_to_land_price_1.geojson'
land_price_path_2 = '/path_to_land_price_2.geojson'
flood_path = '/path_to_flood_data.geojson'
# 各データを読み込む
population_df = pd.read_csv(csv_path, encoding='shift_jis') # 人口データ
town_gdf = gpd.read_file(shp_path) # 町丁字ポリゴン
station_gdf = gpd.read_file(station_path) # 駅データ
land_price_gdf_1 = gpd.read_file(land_price_path_1) # 公示地価1
land_price_gdf_2 = gpd.read_file(land_price_path_2) # 公示地価2
flood_gdf = gpd.read_file(flood_path) # 洪水浸水想定区域
ステップ2:座標系の統一
データの座標系が異なる場合、統一する必要があります。ここではすべて「EPSG:4326」に変換します。
# 座標系を統一(EPSG:4326)
target_crs = 'EPSG:4326'
town_gdf = town_gdf.to_crs(target_crs)
station_gdf = station_gdf.to_crs(target_crs)
land_price_gdf_1 = land_price_gdf_1.to_crs(target_crs)
land_price_gdf_2 = land_price_gdf_2.to_crs(target_crs)
flood_gdf = flood_gdf.to_crs(target_crs)
ステップ3:データの加工
人口データと町丁字データの結合
人口データを町丁字ポリゴンに結合し、人口密度を計算します。
# 町丁字コードを統一フォーマットに変換
population_df['町丁字コード_修正'] = population_df['町丁字コード'].apply(lambda x: f"{int(x):06}")
# ポリゴンデータと人口データを結合
merged_gdf = town_gdf.merge(population_df, left_on='S_AREA', right_on='町丁字コード_修正', how='left')
# 面積と人口密度を計算(平面座標系で面積計算後、再度EPSG:4326に戻す)
projected_gdf = merged_gdf.to_crs(epsg=3857)
projected_gdf['面積m2'] = projected_gdf.geometry.area
merged_gdf = projected_gdf.to_crs(epsg=4326)
merged_gdf['人口密度'] = merged_gdf['総数'] / merged_gdf['面積m2']
工夫した点
平面座標系での面積計算を取り入れ、より正確な人口密度を算出。
小山市と栃木市のデータを抽出
対象地域を「小山市」と「栃木市」に絞り込みます。
# 小山市と栃木市のポリゴンを抽出
target_cities = ['小山市', '栃木市']
oyama_tochigi_gdf = town_gdf[town_gdf['CITY_NAME'].isin(target_cities)]
# 各データを対象地域にクリップ
merged_gdf = gpd.clip(merged_gdf, oyama_tochigi_gdf)
station_gdf = gpd.clip(station_gdf, oyama_tochigi_gdf)
land_price_gdf_1 = gpd.clip(land_price_gdf_1, oyama_tochigi_gdf)
land_price_gdf_2 = gpd.clip(land_price_gdf_2, oyama_tochigi_gdf)
flood_gdf = gpd.clip(flood_gdf, oyama_tochigi_gdf)
工夫した点
gpd.clipを活用して効率的に対象地域に限定。これでストレスなくデータを表示することが可能になります
ステップ4:地図の作成
地図の初期化
地図の中心座標を計算し、Foliumで地図を初期化します。
from pyproj import Transformer
import folium
# 中心座標の計算
projected_gdf = merged_gdf.to_crs(epsg=3857)
center_x = projected_gdf.geometry.centroid.x.mean()
center_y = projected_gdf.geometry.centroid.y.mean()
transformer = Transformer.from_crs("EPSG:3857", "EPSG:4326", always_xy=True)
center_lon, center_lat = transformer.transform(center_x, center_y)
# 地図の作成
m = folium.Map(location=[center_lat, center_lon], zoom_start=12, tiles='cartodbpositron')
人口密度の表示
人口密度をChoroplethで可視化します。
folium.Choropleth(
geo_data=merged_gdf,
data=merged_gdf,
columns=['S_AREA', '人口密度'],
key_on='feature.properties.S_AREA',
fill_color='YlOrRd',
fill_opacity=0.3, # 透過度を調整
line_opacity=0.2,
legend_name='人口密度(人/m²)',
name='人口密度レイヤー'
).add_to(m)
駅情報の表示
駅名と乗降客数をマーカーで表示します。
stations_layer = folium.FeatureGroup(name='駅情報', show=True)
for idx, row in station_gdf.iterrows():
folium.Marker(
location=[row.geometry.y, row.geometry.x],
popup=f"駅名: {row['S12_001']}<br>乗降客数: {row['S12_053']}",
icon=folium.Icon(color='blue', icon='train', prefix='fa')
).add_to(stations_layer)
stations_layer.add_to(m)
洪水浸水想定区域の表示
浸水深ランクに応じた色分けを行います。
flood_colors = {1: 'lightblue', 2: 'blue', 3: 'purple', 4: 'red', 5: 'brown', 6: 'black'}
def flood_style(feature):
code = feature['properties']['A31b_101']
return {'fillColor': flood_colors.get(code, 'gray'), 'fillOpacity': 0.4}
flood_layer = folium.FeatureGroup(name='洪水浸水想定区域', show=False)
folium.GeoJson(flood_gdf, style_function=flood_style).add_to(flood_layer)
flood_layer.add_to(m)
地図の保存
作成した地図をHTMLとして保存します。
m.save('map.html')
おわりに
小山市と栃木市を対象に、Pythonで地理データを可視化する方法を紹介しました。特に以下の点で工夫を施しました:
平面座標系を利用した面積計算で正確な人口密度を算出
効率的な地域クリップ処理でデータ量を削減
浸水深ランク別の色分け表示で視覚的な情報提供
他の地域やデータセットでも試してみてください。