地図上に、描画可能なオープンデータを探してたところ、以下のデータを見つけました。
東京都の区市町村ごとの1人あたりの公園面積等、少しの加工で地図上に描画できそうなデータです。
取り込んで描画してみようと思います。
作成したスクリプト、入力ファイル、出力HTML 一式は以下にUPしてあります。
folium_example/per_capita_park_area_in_tokyo at master · kemsakurai/folium_example
前提
以下環境で作業を実施しています。
-
OS
% sw_vers ProductName: Mac OS X ProductVersion: 10.12.6 BuildVersion: 16G29
-
pythonのverion
% python -V Python 2.7.10
-
使用したfolium のversion
何があったのかはわかりませんが、前回似たようなことを実施してから、1,2週間たらずで、version up していました。。% pip list | grep folium folium (0.5.0)
folium インストール方法
pip でインストールします。
pandas も必要なので、pandas も。
pip install pandas
pip install folium
地図表示についての前提
23区のみの表示に絞ります。理由は以下になります。
* 地域コード付きのGeoJsonデータがすぐに利用可能なもので見つからなかった。
作るのは、、ちょっと面倒かなと思ってしまいました。すみません。
実施作業の流れ
以下の通り作業は実施していきました。
時系列順に記載します。
-
GeoJSON
ファイルの準備 -
データセットの加工
-
地図を描画(コロプレス図)
4 地図を描画(ポップアップ付きのコロプレス図)
GeoJSON
ファイルの準備
前回実施時は、日本の都道府県のデータが必要でしたが、今回は東京都の情報が必要になります。
おそらく誰かが作成してくれているだろうと、思っていたらやはり作成してくれている方がいましたので、拝借して使用させて頂きます。
JapanCityGeoJson/geojson/13 at master · niiyz/JapanCityGeoJson
以下、上記から取得したtokyo23.json
を読み込んで、東京23区を描画するスクリプトになります。
plot_map.py
# -*- coding: utf-8 -
import folium
def main():
# 東京都港区芝公園を設定
tokyo23_location = [35.658593, 139.745441]
m = folium.Map(location=tokyo23_location,
tiles='https://server.arcgisonline.com/ArcGIS/rest/services/Canvas/World_Light_Gray_Base/MapServer/tile/{z}/{y}/{x}.png',
attr='OpenStreetMap',
zoom_start=11)
geojson = r'tokyo23.json'
# geojson読み込み
m.choropleth(geo_data=geojson)
# 地図をhtml形式で出力
m.save(outfile="map.html")
if __name__ == "__main__":
main()
スクリプトの補足説明
-
地図の中心点について
東京都23区の中心部なので、港区あたりかなということで、港区芝公園を設定しました。
経度、緯度などを計算しての結果ではないですが、表示させたところいい感じにはなったので、こちらを採用しています。
tokyo23_location = [35.658593, 139.745441]
-
zoom_start 初期表示時の地図の拡大倍率になります。
これも、値を切り替えて地図出力、表示確認を行って、ちょうど良い大きさsになったのが、11
でそちらを採用しました。
zoom_start=11
-
使用しているtilesについて
folium に バンドルされているもの以外でだと、以下のtile が使用できるようです。
Leaflet Provider Demo
今回使用しているtilesも上記から探して設定しました。
map.html
以下、出力される map.html の描画結果です。
データセットの加工
東京都都市公園等区市町村別面積・人口割比率表 - データセット - 東京オープンデータカタログサイト からcsvをダウンロードします。
地図上にデータを描画するために、geojson上に存在する行政区分コードが必要になります。
csvには、行政区分コードがないため、先頭列に行政区分コードを追加します。
地域名と、地域コードのマッピング表は、やはりJapanCityGeoJson/README.md at master · niiyz/JapanCityGeoJson から取得しました。
Google スプレッドシートで、VLOOKUPして、行政区分コードを追加します。
上記作業を実施後のデータをスクリプトの入力ファイルとしています。
folium_example/koen.csv at master · kemsakurai/folium_example
CSV出力の段階で不要データを排除すべきかとは思いますが、pandas でも加工はできるのでスクリプト上でデータを加工することにしました。
地図を描画(コロプレス図)
データ上、都市公園の指標と、都市公園以外の指標に分かれていて、その合計もあります。
一人当たり面積(ホ/B)(平米)
を用いてコロプレス図を描画します。
作成したスクリプト
長いので、Github上のスクリプトを参照ください。
folium_example/plot_choropleth_map.py at master · kemsakurai/folium_example
スクリプトの補足説明
-
Pandasでのデータ付与について
csv のヘッダーカラムが日本語で、取得の際にエラーとなるため、以下でヘッダ名の変更を行っています。
取得方法があるのかもしれません。# カラムを再設定 df.columns = ["A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z", "AA", "AB", "AC", "AD", "AE", "AF", "AG", "AH", "AI", "AJ"]
-
geojonとのマッピングのための加工 geojsonには、id が String型で定義されています。
A列に行政区分コードが含まれますが、値にNaNが存在するため、float64
になり、このままではマッピングができませんでした。
まず、NaNを0に置き換え、その後 int型に変換し、23区の行政区分コードを含む行のみを抽出。
抽出結果のA列を、String型に変換しています。
# 列Aをint型に変換 df['A'] = df['A'].fillna(0).astype(int) # 23区の地域コードに合致する列のみを抽出 df = df[df['A'].isin([13101, 13102, 13103, 13104, 13105, 13106, 13107, 13108, 13109, 13110, 13111, 13112, 13113, 13114, 13115, 13116, 13117, 13118, 13119, 13120, 13121, 13122, 13123])] # 列、A を文字列に変換 (これをやらないと、数値側と文字列の突き合わせになり、マッピングができない。) df['A'] = df['A'].astype('str')
-
fill_colorの設定について
default はblue
です。
公園なので緑かなということで、'YlGn'
を指定するようにしました。
どんな色が設定できるかですが、folium — Folium 0.5.0+15.gecd5052 documentation に以下のように記載されています。
こちらは、別途まとめようかと思います。- fill_color (string, default ‘blue’) – Area fill color. Can pass a hex code, color name, or if you are binding data, one of the following color brewer palettes: ‘BuGn’, ‘BuPu’, ‘GnBu’, ‘OrRd’, ‘PuBu’, ‘PuBuGn’, ‘PuRd’, ‘RdPu’, ‘YlGn’, ‘YlGnBu’, ‘YlOrBr’, and ‘YlOrRd’.
choropleth_map.html
以下のようなコロプレス図が描画できました。
千代田区が、1人あたりの公園面積が一番広いようです。住んでいる人が少ない、且つ、大きな公園が多いので、納得はしました。
江戸川区が比較的公園面積が広くて、人もたくさん住んでそうですし、そこはちょっとうらやしいかもしれません。
地図を描画(ポップアップ付きのコロプレス図)
一人当たり面積(ホ/B)(平米)
と、総合計((ホ)八+二)数
を使用してポップアップ付きのコロプレス図を描画します。
マーカをクリックすると、ポップアップが表示されるようにします。
作成したスクリプト
長いので、Github上のスクリプトを参照ください。
folium_example/plot_choropleth_map_with_popup.py at master · kemsakurai/folium_example
スクリプトの補足説明
-
ピンを設定している経度、緯度について
ピンを立てる位置は、区の中心がよいかと思い、区の中心の経度、緯度の情報を探したのですが、見つけることができず、geojsonの値から経度、緯度の平均値を導出しました。
以下のメソッド内で計算しています。
# 区の中央部の経度緯度をgeojsonから計算 city_center = __calulate_city_center(data)
-
popup内に表示するtextについて
こちらは、html形式で設定を行う必要があります。
各項目ごとに改行させたかったのですが、\n
記述では設定できず、以下のように<br/>
で記載しました。
city_name = df.loc[(df['A'] == k), 'B'].values[0] poput_text = u"区の名前:" + city_name.decode('utf-8') + "<br/>" square_meter = df.loc[(df['A'] == k), 'AH'].values[0] poput_text = poput_text + u"区の人口一人当たりの公園面積:" + \ str(square_meter) + " " + "m2" + "<br/>" park_count = df.loc[(df['A'] == k), 'AF'].values[0] poput_text = poput_text + u"区の総公園数:" + str(park_count)
choropleth_map_with_popup.html
以下のような地図が描画できました。
公園数を赤系の色で地図に反映、一人あたりの公園面積をピンの大きさに反映させました。
奥さんにできあがったものを見てもらいましたが、奥さんには不評でした。
まとめ
python folium を使い、都道府県の夫婦年齢差をプロットする | Monotalk に続いて、folium で 地図を描きました。
データ取得後、地図に描画するまで、結構なデータ加工が必要です。
それも含めて楽しいといえば楽しいですが、このあたりもうちょっと効率良くできるようになりたいです。
まだ、folium 、leaflet.js の使い方がわかってないところが多く、もっといい感じ描画できないかなと思うようになりました。
もうちょっとドキュメントを読んだりしながら、継続して使い方を調べていこうかと思います。
以上です。
コメント