【浜松市の区再編に対応】市区町村境界ポリゴンデータの作成
こんにちは、新卒1年目のらむです。
私はナビタイムジャパンの交通データ事業にて、主に移動ビッグデータに関するプロダクト開発を担当しています。
交通データ事業では位置情報データや検索データなどを市区町村単位で集計、分析しています。そのなかでも位置情報データと市区町村情報の紐づけやヒートマップによる可視化等で必要となるポリゴンデータを管理しています。
これまで当社で市区町村に関するマスターデータを修正する場合、e-Stat(政府統計の総合窓口)などでデータを取得し、マスターデータを修正していました。しかし今回の浜松市の区再編に伴うポリゴンデータについては対応時点(2024年1月上旬)では公開がされておらず、新たにポリゴンデータを作成する必要がありました。
今回はその中で、どのようにポリゴンデータを作成したのかについてお話しします。また、記事の最後には作成した浜松市の区再編後のポリゴンデータを添付しています。
背景
2024年1月に浜松市の行政区が一部分割・統合されて新たな行政区が再編されました。
このような市区町村情報が変更された際には、サービスで表示しているデータのみならず分析を行う際に使用しているデータについても更新が必要です。近年の市区町村情報の変更では名称変更や市制施行などであったため、名称と市区町村コードの更新のみの対応で十分でした。
浜松市の区再編では分割や統合であるため、名称と市区町村コードに加えて区の境界情報であるポリゴンデータについても更新する必要があります。
市区町村のポリゴンデータは行政区域データとしてe-Stat等で公開されていますが、対応時点(2024年1月上旬)では浜松市の区再編後のポリゴンデータについて見つかりませんでした。そのため、ポリゴンデータを作成する必要があります。
ポリゴンデータの作成
作成の方針として既存の境界データをもとに作成するようにしています。理由としては、作成後の市区町村ポリゴンデータと従来の市区町村ポリゴンデータと境界を一致させて従来の集計結果との差分を最小限にしてデータの整合性を保ちたいからです。
ポリゴンデータの作成については次の手順で行いました。1~3の手順については一般的な手順となっていますが、4の手順については1~3の手順後に問題が発生したため自分で考えた手順となっています。
町丁目ごとの境界データを取得する
取得した町丁目ごとの境界データに新たな市区町村コードを割り当てる
市区町村コードごとに結合する
ポリゴン内の不要な要素を取り除く
1. 町丁目ごとの境界データを取得する
町丁目ごとの境界データの取得に関しては、e-Statの境界データより取得できます。こちらでは町丁目ごとの境界データについて、ShapeファイルやGMLファイル、KMLファイルでダウンロードすることが可能です。今回は、静岡県の境界データについてShapeファイルでダウンロードしました。
2. 取得した町丁目ごとの境界データに新たな市区町村コードを割り当てる
ダウンロードしたデータについて効率的に作業を行うため、地物情報を表形式で扱うことが可能なPythonのライブラリであるgeopandas==0.14.1を使用しました。geopandasは、pipコマンドでインストールが可能です。
pip install geopandas
静岡県のデータから浜松市のデータのみを抽出します。
import geopandas as gpd
shizuoka_shp_path = 'shizuoka.shp' # ダウンロードしたshapeファイルのパス
shizuoka_gdf = gpd.read_file(shizuoka_shp_path)
hamamatsu_gdf = shizuoka_gdf[
shizuoka_gdf["CITY_NAME"].apply(lambda city_name: "浜松市" in city_name)
]
対象のデータフレームに対してplot関数を適用することでレコードごとのポリゴンについて可視化することができます。
hamamatsu_gdf.plot()
各レコードに対して新たな区名の割り当てを行います。
def get_new_city_name(row):
if row["CITY_NAME"] == "浜松市北区":
if row["S_NAME"] in [
"初生町",
"根洗町",
"三方原町",
"東三方町",
"豊岡町",
"大原町",
"三幸町",
]:
return "浜松市中央区"
else:
return "浜松市浜名区"
elif row["CITY_NAME"] == "浜松市浜北区":
return "浜松市浜名区"
elif row["CITY_NAME"] == "浜松市天竜区":
return "浜松市天竜区"
return "浜松市中央区"
hamamatsu_gdf["new_city_name"] = hamamatsu_gdf.apply(get_new_city_name, axis=1)
3. 市区町村コードごとに結合する
対象のデータフレームに対して、dissolve関数を適用することで指定したカラムが一致するレコードについて結合を行います。
dissolved_gdf = hamamatsu_gdf.dissolve(by=["new_city_name"], as_index=False)
plot関数で可視化することで区再編後のポリゴンデータが確認できました。
4. ポリゴン内の不要な要素を取り除く
別の可視化ツールで確認すると、作成したポリゴン内部に黒くてもやもやした不要な部分が存在することが分かります。これは、ポリゴン同士に微妙な隙間があったため、結合の際に不要な部分が発生したものと考えられます。
ポリゴン内の不要な部分の削除については、グループ化された複数のポリゴンの中から一番大きなポリゴンのみを抽出することで対応しました。交通データ事業ではヒートマップを作成する際にポリゴンデータを使用しますが、湖や小さな島などの詳細な描画は必要ありません。浜松市の区再編後の区に関して大きな飛び地も存在しないため、一番大きなポリゴンのみの抽出のみで十分と判断しました。
対応する区の数が多くないため、ポリゴンデータをWKT(Well-known text)形式にしたのちテキストエディタ上で一番大きなポリゴンのみが残るように抽出しました。その結果、以下のように不要な部分の生じてないポリゴンが完成しました。
(補足)
精密なポリゴンを必要とする場合では今回行った方法ではなく、手作業で不要なポリゴンを除去する方法やポリゴンの結合前にポリゴンの精度を落として隙間を埋める方法などがある。
まとめ
今回は浜松市の区再編後におけるポリゴンデータの作成について説明しました。今後も使用したいタイミングでポリゴンデータが存在しない場面があると思います。その際にないなら作るという選択肢もあると、対応がスムーズにできるかと思います。
作成した浜松市のポリゴンデータについてはこちらからダウンロードすることができます。ぜひ分析・可視化等に役立てていただけると幸いです。
※使用に関しては自己責任でお願いします。