【Python】市区町村レベルの塗り分け地図プロット

# この記事の目的

Pythonで以下の様な, 市区町村レベルの塗り分け地図を描く
都道府県レベルなら[こちら](https://qiita.com/yuto16/items/fa2c4d8b79e4d09defcd)へ

![plot08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/540956/eec08c1b-23ff-199a-a61e-947722b5ac4a.png)

当初は, geopandas + geoplotで行おうと思っていたが, Google Colabでgeoplotがうまくインストールできなかったため, geoplotを諦めいろいろ行錯誤して, 最もシンプルであろう方法にたどり着いた. 
基本的にgeopandasが追加でインストールできればOK. 

ちなみに塗り分けの色は, 今回は乱数の値を元にしているので, 適宜データを変えてもらいたい. 

ページの最後に[コード一覧](#コード一覧)があります.

# 解説

色付きの地図を作成するために, [geopandas](http://geopandas.org/) というライブラリを用いる

```bash
pip install geopandas
```


その他ライブラリの準備

```python
import numpy as np
import geopandas as gpd
import random
import matplotlib.colors
import matplotlib.pyplot as plt
```

市区町村の形(ポリゴン)のデータを[「国土数値情報　ダウンロードサービス」](http://nlftp.mlit.go.jp/ksj/index.html)からダウンロードして適当な編集ソフト(QGISなど)で前処理を行う. 

前処理で必ず行うこととしては, 以下のように, 同じ市区町村なのに複数のポリゴンからなるデータを１つにまとめなければならない. また, 必要に応じて, ポリゴンの簡素化なども行う. 
 

![plot07.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/540956/4b0c0e7e-8b66-5450-5837-b6d59da77617.jpeg)
QGISを使う場合は[ここ](https://sites.google.com/site/qgisnoiriguchi/vector01/09)などを参考にしてもらいたい.

前処理が済んだデータをgeojson形式でエクスポートして, これをgeopandasで読み込む
ファイルのディレクトリは適宜変えてもらいたい. 

```python
filename = "/content/drive/My Drive/Colab Notebooks/pref47.geojson"
df = gpd.read_file(filename, encoding='SHIFT-JIS')
```

また, 塗り分けに使うデータをここでgeopandas形式のデータフレームに追加する. 
使い方は, pandasと同様なのでわかりやすい. 
今回は簡単のために, ランダムな値を用いているが, ここに人口や賃金などのデータを入れることを想定している. 

```python
df["target"] = [random.random() for i in range(df.shape[0])]
```

市区町村ごとのデータから, 塗り分けを行う色を決定する関数を定義しておく

```python
def colors_scale(arr):
    n_min = min(arr)
    n_max = max(arr)
    cmap = plt.cm.rainbow
    norm = matplotlib.colors.Normalize(vmin=n_min, vmax=n_max)

    arr = [cmap(norm(r)) for r in arr]
    return arr, cmap, norm
```

最後に地図のプロット
pandasと同様の書き方で, 興味のあるデータだけを選択してmini_dfとしている. 
df.plotを行うときにcolor=で色情報のリストを渡すのがポイント

```python
mini_df = df[df["N03_001"].isin(["愛媛県", "徳島県", "香川県", "高知県"])]

target_color, cmap, norm = colors_scale(mini_df["target"])

mini_df.plot(color=target_color, figsize=(10,6))
sm = plt.cm.ScalarMappable(cmap=cmap, norm=norm)
plt.colorbar(sm)
plt.show()
```


以上！

# コード一覧

```bash
pip install geopandas
```

```python
import numpy as np
import geopandas as gpd
import random
import matplotlib.colors
import matplotlib.pyplot as plt

filename = "/content/drive/My Drive/Colab Notebooks/pref47.geojson"
df = gpd.read_file(filename, encoding='SHIFT-JIS')

df["target"] = [random.random() for i in range(df.shape[0])]

def colors_scale(arr):
    n_min = min(arr)
    n_max = max(arr)
    cmap = plt.cm.rainbow
    norm = matplotlib.colors.Normalize(vmin=n_min, vmax=n_max)

    arr = [cmap(norm(r)) for r in arr]
    return arr, cmap, norm


mini_df = df[df["N03_001"].isin(["愛媛県", "徳島県", "香川県", "高知県"])]

target_color, cmap, norm = colors_scale(mini_df["target"])

mini_df.plot(color=target_color, figsize=(10,6))
sm = plt.cm.ScalarMappable(cmap=cmap, norm=norm)
plt.colorbar(sm)
plt.show()

```

# 参考
[国土数値情報　ダウンロードサービス](http://nlftp.mlit.go.jp/ksj/index.html)
[09.いくつかの地物をまとめて一つの地物にする](https://sites.google.com/site/qgisnoiriguchi/vector01/09)
[pythonを用いたshapefileやgeojsonの読込および描画](https://qiita.com/HidKamiya/items/5e7240f8f66c9af8b10e)