地域分析に最適!Plotlyを使った人口・世帯数のコロプレスマップ作成方法

Plotlyというデータ可視化のPythonライブラリーを使って、奈良の地域人口別コロプレスマップを作ってみます。

Google Colabのコードも公開しているので、実際に動かしてみてください。

コード解説します

統計データを準備する

行政区域データをダウンロード

行政区域の境界線データを国土交通省の国土数値情報ダウンロードサービスから取得します。

# 奈良県の令和四年度行政区域データ(国土交通省)
!wget https://nlftp.mlit.go.jp/ksj/gml/data/N03/N03-2022/N03-20220101_29_GML.zip
!unzip N03-20220101_29_GML.zip

ダウロードされたファイルのgejsonファイルを使います。

市町村の人口データをダウンロード

総務省の市区町村別の人口及び世帯数のエクセルデータをダウンロードします。

#総務省 奈良県の市区町村別の人口及び世帯数
!wget https://www.soumu.go.jp/main_content/000033865.xls

データの前処理を行う

このエクセルデータの市町村表記とgeojsonのファイルの形式があっていないので、表記統一のために前処理をします。

左のgeojsonのコラムでは「郡」を抜いた市町村単位なので、右側の人口及び世帯数エクセルデータのコラムの表記を合わせます。

分量も少ないので、最初は表計算ソフトで手動や検索置換で行ったのですが、手動部分をなくすためにpythonで処理しました。

    # XLSファイルから人口データフレーム作成
    df = pd.read_excel (r"/content/000033865.xls", header=1)

    # 市町村名から重複などを取り除く
    df["団体名"] = df["団体名"].replace(re.compile(r"(.+?郡)(.+?[町村])"), r"\2", regex=True)
    df=df[~df["団体名"].str.endswith('郡', na=False)]
    df=df[~df["団体名"].str.endswith('県', na=False)]

ちなみに、ダウンロードしたエクセルファイルを読み込む手順ですが、通常なら、Openpyxlというライブラリを使って読み込むのが一般的ですが、総務省にあるファイルが旧式のxlsファイルなので、読み込めません。

そこで、Pandasライブラりにある「pd.read_excel」で直接読み込むことにします。

今回の場合こちらのほうが簡潔で手順も減るので良いですね。

読み込むファイルに必要のない行があるので「, header=1」という引数で最初の行を飛ばして読み込みます。

これで、人口データがPandasのデータフレームに読み込まれました。

市町村名を修正する

    # 市町村名から重複などを取り除く
    df["団体名"] = df["団体名"].replace(re.compile(r"(.+?郡)(.+?[町村])"), r"\2", regex=True)
    df=df[~df["団体名"].str.endswith('郡', na=False)]
    df=df[~df["団体名"].str.endswith('県', na=False)]

最初の行で「吉野郡吉野町」という表記の先頭の「吉野郡」のような郡名を取り除きます。

二行目は、「吉野郡」のような郡名のみの行を削除します。

三行目は「奈良県」のような県名のみの行を削除します。

これで、geojsonファイルにあわせた表記になりました。

コラム名の修正と数値型と表記の修正

    # コラム名を変更し、数値型に変換する
    df.columns = ['市区町村名', '男', '女', '計', '世帯数']
    df[['男', '女', '計', '世帯数']] = df[['男', '女', '計', '世帯数']].replace(',', '', regex=True).astype('float')

ここは特に行わなくても良いのですが、元のエクセルファイルにある市町村名が「団体名」となっていたので、「市区町村名」に変更しておきます。

そして、人口や世帯数の表記に「、」カンマが含まれているので、それを取り除き、データ型を「文字型(object型)」から「小数点型(float16型)」に変更します。

これで前処理は終わりです。

プラグインのインストール

Google Colabには標準に含まれないライブラリをインストールしておきます。

!pip install geocoder

ご自身のmacやwindowsなどのローカル環境で行う場合は必要なライブラリはインストールしてください。(ご自身の環境にplotlyをインストール場合はNode.jsなどのインストールが別途必要になります)

import json
import re
import pandas as pd
import plotly.express as px
import geocoder as geocoder #geocoderのみ要別途インストール

地図を描画する

geojsonのデータを読み込んでおきます。

    # GeoJSONファイルから地図データ読み込み
    with open(geojson_file) as f:
        geojson = json.load(f)
        # ジオジェイソンデータから不要な列を削除する
        for feature in geojson['features']:
            feature['properties'].pop('N03_001')
            feature['properties'].pop('N03_002')
            feature['properties'].pop('N03_003')
            feature['properties'].pop('N03_007')

    return df, geojson

不要な列を削除しなくても問題ありませんが、市町村名の含まれる「N03_004」以外は必要ないので取り除いて読み込んでおきます。

これで、市町村の人口データが「df」地図の境界線情報を「geojson」として格納しておきます。

地図の描写を行う

def plot_map(df, geojson, prefecture):
    """データフレームとジオジェイソンから地図をプロットする"""
    # 都道府県の中心座標を取得
    center_latlng = get_center_latlng(prefecture)
    fig = px.choropleth_mapbox(
        df, #人口データ
        geojson=geojson, #市町村境界線のポリゴンデータ
        locations="市区町村名", 
        color="計", #地域の人口にあわせて色を変化させる
        hover_name="市区町村名",
        hover_data=["男", "女", "世帯数"], # マウスオーバーした時に表示される値
        featureidkey="properties.N03_004", #geojsonデータから「市区町村名」に対応するキー
        mapbox_style=MAPBOX_STYLE, #描画する地図のスタイル
        range_color=COLOR_RANGE,
        zoom=ZOOM_LEVEL,
        center={"lat": center_latlng[0]-0.5, "lon": center_latlng[1]}, 
        opacity=OPACITY,
        width=FIG_SIZE,
        height=FIG_SIZE,
    )
    fig.update_layout(margin=dict(b=0, t=0, l=0, r=0))
    fig.show()

事前によみ込まれた二つのファイルを取り込み地図描写を行います。

# 都道府県の中心座標を取得
center_latlng = geocoder.arcgis(prefecture).latlng

まず表示する中心を「奈良県」の座標に合わせます。geocoderライブラリによって、わざわざ緯度経度情報を入れる必要がなくなります。

ただ、奈良県だと県庁所在地が北部なので緯度を「-0.5」して中心部分を南下させています。

center={"lat": center_latlng[0]-0.5, "lon": center_latlng[1]}

メイン処理

# メイン処理
if __name__ == "__main__":
    df_nara, geojson_nara = load_data(XLS_FILE, GEOJSON_FILE)
    plot_map(df_nara, geojson_nara, PREFECTURE)

一連の処理を実行して地図を描画します。

10数行のコードでこうした地図ができ上がるので、便利ですね。市区町村の表記揺れの前処理部分は地域によっては変わると思いますが、(そのあたり汎用性あるスクリプトをそのうち書き直しに挑戦したいと思います)ぜひ試してみてください。

Shareこの記事をシェアしよう!

モバイルバージョンを終了