いわゆる白地図に色を塗ったもの。最近めっきりpythonを使わなくなってしまったのもあるし、そういえばGeo的なことにも全く触れていなかったので、なんかしてみようという気になった。こういうときは、とりあえずほんとに簡単なものから手をつけるべし、である。久しぶりにjupyterを起動した。
<環境>
・Windows10
・python 3.7
・Anaconda
調べてみると、こういうのはコロプレス図っていうらしい。pythonで描く場合には、foliumかgeopandasを使う。foliumは前職でも少しだけお世話になった。たぶん、見ばえ的にもfoliumの方がいい。OpenStreetMapを下敷きにできるのは素晴らしいと思う。
が、今回はgeopandasを使った。国交省のgeojsonファイルを読み込むところで詰まってしまったのである。shpファイルなら読み込めたのかもしれないけど、試してない。。。あと、余談だけど、こういうデータが国土地理院じゃないのが、ちょっと意外だ。なぜだろう。
というわけで、以下のサイトから岐阜県の地図情報をダウンロードする。形式とかはいろいろとよくわかんないけど、欲しいのは市町村別の地図だから行政区域ってやつから最新のデータをもってきた。
nlftp.mlit.go.jp
まずはインポートして、ファイルを読み込む。geopandasはシェープファイルを使うらしい。
import pandas as pd import geopandas as gpd import matplotlib.pyplot as plt fp = r"N03-20210101_21_GML/N03-21_21_210101.shp" geo_data = gpd.read_file(fp, encoding="sjis") geo_data.head()
頭出しをしてみるとこんな感じ。シェープファイルの中身って見たことがなかった。geometryってのに緯度経度っぽいものが入ってる。境界線を緯度経度で指定して描いてるってことなのかも。だとしたら、結構なデータ量になりそうなもんだが、どうなんだろう。
あと、どうやらencodingはsjis指定が必要だった。ここで1つ詰まった。
一旦、地図にしてみる。シェープファイルをプロットするだけの簡単操作。これはお手軽だった。
geo_data.plot(color="lightseagreen", linewidth=0.5, edgecolor="lightgray", figsize=(5, 5))
ここまでくればなんとなくわかる。たぶん、geopandasのデータフレームに数値くっつけたらいいのだろう。ってことで、岐阜県のページから人口データをダウンロードしてみた。
gifu-opendata.pref.gifu.lg.jp
ちょっと予想を上まわる形式でダウンロードできた。使用したのは平成27年国勢調査人口等基本集計結果ってやつだが、エクセルでこんなのになっている。
まぁ、いろんな種類のデータを載せるから仕方ないのかもしれないが、ちょっとこのままでは読み込めない。仕方がないので、エクセルで形を整えて読み込んだ。
pop_data = pd.read_csv("kokuchokihon2015-5.csv")
pop_data.head()
あとはこのデータをシェープファイル読み込んだデータフレーム(今回はgeo_data)にマージ(くっつける)する。結合のキー情報が市町村名しかなさそうなので、日本語でjoinってのはちょっと気がひけるけど仕方なし。
気をつけなきゃいけないのは、地図のデータと人口データの行数が違うこと。市町村の飛び地なんかもあるので、地図データの方が行数が多い。例えば「大垣市」が複数行ある。今回はあくまで市町村別での塗り分けを目指すってことで、left outer joinな感じにしている。
map_data = geo_data.merge(pop_data, left_on='N03_004', right_on='市町村', how="left") map_data.head()
最後にplotするだけ。タイトルとか凡例とかをつけてるので、ちょっと細かくなってるが、基本的にはplotにcolumnを指定してあげるだけで色を塗ってくれる。
fig, ax = plt.subplots(1, 1, figsize=(10, 8)) ax.set_title('population of Gifu pref. 2015', fontsize=18) map_data.plot(column='人口_H27', ax=ax, cmap='OrRd', edgecolor='gray', legend=True ) fig.savefig('population of Gifu pref .jpg', dpi=200)
うーん、これで完成なんだけど、なんかおもしろくない。結局岐阜市に人口が集中し過ぎているので、あんまり塗り分けられてない。なので、ここからはアディショナルタイムとして、人口増減率で塗ってみることしにした。
map_data['人口増減'] = map_data['人口_H27'] - map_data['人口_H22'] map_data['人口増減率'] = ( map_data['人口増減'] / map_data['人口_H22'] ) * 100 fig, ax = plt.subplots(1, 1, figsize=(10, 8)) ax.set_title('increase - decrease rate of population 2010 to 2015', fontsize=18) map_data.plot(column='人口増減率', ax=ax, cmap='coolwarm', edgecolor='gray', legend=True )
カラフルになった。けど、けど、なんか違う。もっと人口は減ってるはずなのである。凡例見ればわかるけど「0.0」がオレンジじゃいけない。そこは白にすべきだっ!
import matplotlib.colors as mcolors # normalize color vmin, vmax, vcenter = -15, 15, 0 norm = mcolors.TwoSlopeNorm(vmin=vmin, vcenter=vcenter, vmax=vmax) # create a normalized colorbar cmap = 'coolwarm' cbar = plt.cm.ScalarMappable(norm=norm, cmap=cmap) # create a map fig, ax = plt.subplots(1, 1, figsize=(10, 8)) ax.set_title('increase - decrease rate of population 2010 to 2015', fontsize=18) map_data.plot(column='人口増減率', ax=ax, cmap='coolwarm', edgecolor='gray', norm=norm, legend=False) # add colorbar fig.colorbar(cbar, ax=ax) fig.savefig('increase - decrease rate of population.jpg', dpi=200)
結局、まっ青になった。。。(これが現実でもある)
m(_ _)m