農業のデータを日本地図で可視化してみた

# はじめに
データの可視化はmatpotlibやseabornでグラフで表示したり、表で表示したりしますが、地図上で表示した方が分かりやすいデータもあると思います。
例えば、北海道の各地域の魚の収穫量に応じて地域ごとに色塗りされているものがあれば分かりやすいと思います。

例えば、このように
![スクリーンショット 2023-09-25 15.15.58.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/603047/211e900c-743c-5553-01f7-eda6efbf386a.png)
(https://www.maff.go.jp/j/tokei/ より引用)
福岡県を例に市町村ごとに農業データを地図上に可視化してみました。

# 使ったサイト
・国土数値情報（国土交通省）
https://nlftp.mlit.go.jp/ksj/
このサイトでは市町村のプロットのためにgeojsonファイルを使用しています

・農林水産省-統計情報
https://www.maff.go.jp/j/tokei/index.html
このサイトでは農業の各種データのあるCSVファイルを使用しています

# 環境
```
Python 3.11.5
pandas 2.1.0
numpy  1.26.0
folium 0.14.0
```
foliumという地図を簡単に作成できるPythonのライブラリを使用します。

https://python-visualization.github.io/folium/latest/

# 環境構築
```
pip install pandas numpy folium
```

# コード
```python
import json
import folium
import numpy as np
import pandas as pd

pd.options.display.max_rows = 100
pd.options.display.max_columns = 100

def create_map():
    map_obj = folium.Map(location=[35, 135], zoom_start=5)

    # 区域データの読み込み
    geo_data = './data/N03-23_40_230101.geojson'

    # 農業算出額のファイルを読み込み
    df = pd.read_csv('./data/e033-03-k000.csv', skiprows=10)

    # 指定されたカラム名に変更
    df.columns = [
        '都道府県', '市町村', '都道府県コード', '市町村コード', '単位', '農業産出額', '耕種', '米', '麦類',
        '雑穀', '豆類', 'いも類', '野菜', '果実', '花き', '工芸農作物', '茶', 'その他作物', '畜産',
        '肉用牛', '乳用牛', '生乳', '豚', '鶏', '鶏卵', 'ブロイラー', 'その他畜産物', '加工農産物'
    ]

    # 不要な列を削除
    df = df.drop(columns=['単位'])

    # 福岡だけ
    df = df[df['都道府県'] == '福岡']
    # 福岡市、北九州市の市町村コードをgeojsonに合わせる
    df['市町村コード'] = df['市町村コード'].replace(100, 101)
    df['市町村コード'] = df['市町村コード'].replace(130, 135)

    # 欠損値(-,x)、カンマを削除
    for col in df.columns[4:]:
        df[col] = df[col].astype(str)
        df[col] = df[col].replace(['-', 'x'], np.nan)
        df[col] = df[col].str.replace(',', '')
        df[col] = df[col].astype(float)

    # 文字列カラムの前後の空白を削除
    df['都道府県'] = df['都道府県'].str.strip()
    df['市町村'] = df['市町村'].str.strip()

    # 都道府県コードと市町村コードを連携したカラムを追加(geojsonのN03_007と一致)
    df['code'] = df['都道府県コード'].astype(str) + df['市町村コード'].astype(str)

    def style_function(feature):
        city_name = feature['properties']['N03_003']
        if city_name in ['福岡市', '北九州市']:
            value = df[df['市町村'] == city_name]['農業産出額'].values[0]
        else:
            code = feature['properties']['N03_007']
            value = df[df['code'] == code]['農業産出額'].values[0] \
                if code in df['code'].values else 0
        color_scale = folium.LinearColormap([
            'white', 'red'],
            vmin=df['農業産出額'].min(),
            vmax=df['農業産出額'].max()
        )
        return {
            'fillColor': color_scale(value),
            'fillOpacity': 0.6,
            'weight': 1,
            'color': 'black',
        }

    # geo_dataの読み込み
    with open(geo_data, 'r', encoding='utf-8') as f:
        geo_data_json = json.load(f)

    # 各フィーチャをマップに追加
    folium.GeoJson(
        geo_data_json,
        style_function=style_function
    ).add_to(map_obj)

    folium.LayerControl().add_to(map_obj)

    return map_obj


# 地図を作成
map_obj = create_map()

# 地図をHTMLファイルに保存
map_obj.save('index.html')
```

作成された地図(index.html)がこちら
![スクリーンショット 2023-09-25 16.49.41.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/603047/b454722b-0aa8-3b0a-ff4d-417ed56cbd5b.png)

福岡県にズームしてみます
![スクリーンショット 2023-09-25 16.49.26.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/603047/6230d234-bdb0-31ae-61b4-baa0dff9c4bb.png)

綺麗な海と橋で有名な糸島市と
豚骨ラーメン発祥(諸説あり)の久留米市と
ホリエモンさん出身で高級茶葉八女茶の八女市で農業が活発のようです。

# 解説
途中、複雑なコードがありますが、
福岡県の福岡市や北九州市のように行政区が別れている区政の市では、CSVを読み込んだDataFrameとgeojsonを読み込んだDataFrameをがっちゃんこしても1つの区だけマッピングされ、他の区は表示されないため、全ての行政区で色の塗りつぶしがされるようにコーディングしています

佐賀県などの行政区が無い都道府県であれば下記のようにするとシンプルに書けます
```python
# レイヤー作成
folium.Choropleth(
    geo_data=geo_data,
    name='農業算出額',
    data=df,
    columns=['code', '農業産出額'],
    key_on='feature.properties.N03_007',
    fill_color='PuRd',
    fill_opacity=0.6,  # 塗りつぶしの濃淡
    line_opacity=0.2,  # 境界線の濃淡
    legend_name='農業産出額',
).add_to(map_obj)
```
def style_function(feature)
から
folium.GeoJson()
の部分を上記に書き換えてください。

```python
df = df[df['都道府県'] == '福岡']
```
市町村の区域データの全国版を使用すると、マップの作成が上手くいかないため、今回は福岡県に限定しています。
九州地方など、ブロックレベルまでは地図に可視化できそうです。
全国版のものが1つのPythonファイルでできないか試行してみます。

```python
df['市町村コード'] = df['市町村コード'].replace(100, 101)
df['市町村コード'] = df['市町村コード'].replace(130, 135)
```
また、農業のCSVデータと市町村区域のgeojsonデータの市町村コードに相異があり
コード上で片方に合わせるコードを書いています。
役所のたいていのデータは一致しているはずですが、国土交通省と農林水産省とでは相異がありました。そのため同じ省庁のデータに触れる場合にデータの修正が必要です。
実際にデータ分析に入る前に、前処理の段階でコードの修正をしましょう。


データ分析の勉強にどうぞ

https://qiita.com/wooooo/items/24d1a4d6be5ab7bf023f