【Python】日本地図の市区町村をMatplotlibのbasemapを使って表示する

# 都道府県はBIツールでどうにかなるが、市区町村の地図は自分で作成しなきゃいけいない
BIツールで調べていくと、tableauでは一応できるが、ツールがないとどうしようもない事象が発生した。
調べていくと、どうもPythonでも同じようなことができるようなので、その導入方法を紹介する。

# 参考
↓のURLに参考にした記事を張っておくので、元ソースが見たいときはこちらをご覧ください。
- https://qiita.com/ty21ky/items/271274a7057d32061cb3

# 実行環境
- OS : Windows 10 Home
- Python : Ver 3.7
- Install Tool: Anaconda

# 最初にやること
BasemapはCondaでインストールできるので、そこからインストールする。
※もちろん、インターネットに接続できる状態で行う
```conda install -c anaconda basemap```
　
# 必要なデータを準備する
国土数値情報ダウンロードページから該当する都道府県を探し、登録された時期のデータをダウンロードする。
今回は参考にしたがって、奈良のデータを取得する。
https://nlftp.mlit.go.jp/ksj/gml/datalist/KsjTmplt-N03-v2_3.html#prefecture29

また、参考URL(https://qiita.com/ty21ky/items/271274a7057d32061cb3)にある奈良の人口数のデータを流用する

```nara.csv
area,支庁市郡,区町村,ふりがな,population_2016
29200,,,,
29201,奈良市, ,ならし,358786
29202,大和高田市, ,やまとたかだし,64156
29203,大和郡山市, ,やまとこおりやまし,86466
29204,天理市, ,てんりし,67012
29205,橿原市, ,かしはらし,123640
29206,桜井市, ,さくらいし,56763
29207,五條市, ,ごじょうし,30369
29208,御所市, ,ごせし,26502
29209,生駒市, ,いこまし,118084
29210,香芝市, ,かしばし,78103
29211,葛城市, ,かつらぎし,36720
29212,宇陀市, ,うだし,30415
29320,山辺郡, ,やまべぐん,
29322,山辺郡,山添村,やまぞえむら,3578
29340,生駒郡, ,いこまぐん,
29342,生駒郡,平群町,へぐりちょう,18736
29343,生駒郡,三郷町,さんごうちょう,23573
29344,生駒郡,斑鳩町,いかるがちょう,27267
29345,生駒郡,安堵町,あんどちょう,7415
29360,磯城郡, ,しきぐん,
29361,磯城郡,川西町,かわにしちょう,8435
29362,磯城郡,三宅町,みやけちょう,6813
29363,磯城郡,田原本町,たわらもとちょう,31477
29380,宇陀郡, ,うだぐん,
29385,宇陀郡,曽爾村,そにむら,1508
29386,宇陀郡,御杖村,みつえむら,1697
29400,高市郡, ,たかいちぐん,
29401,高市郡,高取町,たかとりちょう,7087
29402,高市郡,明日香村,あすかむら,5483
29420,北葛城郡, ,きたかつらぎぐん,
29424,北葛城郡,上牧町,かんまきちょう,21903
29425,北葛城郡,王寺町,おうじちょう,23218
29426,北葛城郡,広陵町,こうりょうちょう,33568
29427,北葛城郡,河合町,かわいちょう,17742
29440,吉野郡, ,よしのぐん,
29441,吉野郡,吉野町,よしのちょう,7159
29442,吉野郡,大淀町,おおよどちょう,17729
29443,吉野郡,下市町,しもいちちょう,5500
29444,吉野郡,黒滝村,くろたきむら,637
29446,吉野郡,天川村,てんかわむら,1311
29447,吉野郡,野迫川村,のせがわむら,424
29449,吉野郡,十津川村,とつかわむら,3399
29450,吉野郡,下北山村,しもきたやまむら,858
29451,吉野郡,上北山村,かみきたやまむら,488
29452,吉野郡,川上村,かわかみむら,1267
29453,吉野郡,東吉野村,ひがしよしのむら,1662
```
 
# 実行するソース

```test.py
import matplotlib.cm
#import matplotlib as mpl
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
from matplotlib.patches import Polygon
from matplotlib.collections import PatchCollection

from matplotlib.colors import Normalize
from mpl_toolkits.basemap import Basemap # ←エラーがでなければOK

font = {'family': 'MS Gothic'} #日本語Fontを指定
nara_file_path = '<your file path>'
po_nara = pd.read_csv(nara_file_path, encoding='sjis') # .csv読み込み

fig, ax = plt.subplots(figsize=(10,20))

# llcrnrlon, llcrnrlat: Min longitude, Min latitude
# urcrnrlon, urcrnrlat: Max longitude, Max latitude
map = Basemap(llcrnrlon=135.5,llcrnrlat=33.7,urcrnrlon=136.3,urcrnrlat=34.9)


# map_shape_file_path = '<your .shp file path & name>'
map_shape_file_path = '<your .shp file base path>/N03-180101_29_GML/N03-18_29_180101'
map.readshapefile(map_shape_file_path, 'nara', color='#444444', linewidth=.2, default_encoding='utf8') # 奈良県のシェイプファイル読み込み

#奈良県のシェイプファイルからDataFrameを作成
df_poly = pd.DataFrame({
        'shapes': [Polygon(np.array(shape), True) for shape in map.nara],
        'area': [area['N03_007'] for area in map.nara_info]
    })

df_poly['area'] = df_poly['area'].astype(np.int64)

#上記で作成したDataFrameに人口の入ったcsvの内容をmergeする。
#この段階でエラーがでました。
df_poly = df_poly.merge(po_nara, on='area', how='left')

cmap = plt.get_cmap('Oranges')   
pc = PatchCollection(df_poly.shapes, zorder=2)
norm = Normalize()

pc.set_facecolor(cmap(norm(df_poly['population_2016'].fillna(0).values)))
ax.add_collection(pc)

mapper = matplotlib.cm.ScalarMappable(norm=norm, cmap=cmap)

mapper.set_array(df_poly['population_2016'])
plt.colorbar(mapper, shrink=0.4) #カラーバー

plt.title('平成xx年　奈良県市町村別人口', fontsize=15, **font)

plt.show()
```

# さらに町域などでもデータが見たい場合は…
上記のデータでは市区町村までしかデータの可視化はできません。
ですが、もっと粒度の細かな情報が提供されているので、そちらからデータを取得できれば
地図に対してheatmapが作成できます。

## ダウンロードパス
https://www.e-stat.go.jp/gis/statmap-search?page=1&type=2&aggregateUnitForBoundary=A&toukeiCode=00200521&toukeiYear=2015&serveyId=A002005212015

このパスに町域以下のメッシュデータがあるので、これを適宜使用して、用途に合わせて↑と同じことをすれば動きます。

# 最後に
今回はPythonを使用していきました。
実際に使用したかったのはオフラインでの利用でしたが、スピード重視でやるためにオンラインでの作業で動作確認しています。
もし、オフラインで市区町村以下のマッピングができる方法があれば、情報共有していただけると嬉しいです。

最後までご高覧いただきましてありがとうございました。