やりたいこと
日頃、GoogleAnalyticsや会社独自のデータを取り扱う機会が多い。そうした情報を地図上にプロット。営業・広告戦略立案に役立てたい。ということで冒頭に乗ってる地図情報がサンプル。ヒートマップにて表示されていて「なんか凄いんじゃないか?」感がでていて非常によい。できれば、こういうもので会社の偉い人らを立て続けに殴打したい。
用意するもの
Jupyter notebook
Folium
pandas
json
requests
matplotlib
EstatのAPIアカウント
https://www.e-stat.go.jp/api/apiuser/provisional/
ライブラリ系は全てpipしておけばよいです。
Githubにて
https://github.com/kerion546/folium_estat
今回のコードはここからダウンロードできます。
考えながら作っていく
1. E-statからのデータ取得
会社データ使うわけにはいかないので、オープンデータ探していたら、あるらしい。Estatというらしい。
「政府統計の総合窓口(e-Stat)」は、各府省が公表する統計データを一つにまとめ、統計データの検索をはじめとした、さまざまな機能を備えた政府統計のポータルサイトです。各府省が公表している統計表をExcel・CSV・PDF形式でダウンロードすることが可能です。
とのことなので、ここを使うことにした。APIではアカウント登録をすることで、JSONやXMLでGETすることができて簡単に情報が収集できる。今回は練習を兼ねてJSONでの取得を行った。
1 2 3 4 5 6 7 8 9 10 11 12 |
import json, requests #E-stat のAPIの使い方参照 appid = 'YOUR APPID' statsdataid = '0003159141' paramid = '&cdCat01=054&cdCat02=004' url_estat = 'http://api.e-stat.go.jp/rest/2.0/app/json/getStatsData?appId={}&statsDataId={}{}'.format(appid, statsdataid, paramid) res = requests.get(url_estat) json_res = json.loads(res.text) json_res |
2. E-statからのデータ整形
json_resでJupyter Notebookの場合取得データが表示される。非常に汚い。なんだこれはという感じ。paramidである程度情報を絞ってますが、全体像を見たい人は、パラメータ削除の上、データを見てね。ここからもう少しデータをわかりやすく整形していく。
※「こんくらいのデータなら、最初からエクセルで整形した方がいいだろ」と思われた方。正解だと思います。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 |
#JSONが見づらかったのでVALUEに絞ってjson_statへ代入 json_stat = json_res['GET_STATS_DATA']['STATISTICAL_DATA']['DATA_INF']['VALUE'] area = [] increace = [] for stat in json_stat: area.append(stat['@area']) increace.append(stat['$']) from pandas import DataFrame import pandas as pd df = pd.DataFrame({"area" : area, "increace" : increace}) #面倒なのでJupyter Notebookで出力してコピった todohuken = [{'@code': '01000', '@level': '1', '@name': '北海道'}, {'@code': '02000', '@level': '1', '@name': '青森県'}, {'@code': '03000', '@level': '1', '@name': '岩手県'}, {'@code': '04000', '@level': '1', '@name': '宮城県'}, {'@code': '05000', '@level': '1', '@name': '秋田県'}, {'@code': '06000', '@level': '1', '@name': '山形県'}, {'@code': '07000', '@level': '1', '@name': '福島県'}, {'@code': '08000', '@level': '1', '@name': '茨城県'}, {'@code': '09000', '@level': '1', '@name': '栃木県'}, {'@code': '10000', '@level': '1', '@name': '群馬県'}, {'@code': '11000', '@level': '1', '@name': '埼玉県'}, {'@code': '12000', '@level': '1', '@name': '千葉県'}, {'@code': '13000', '@level': '1', '@name': '東京都'}, {'@code': '14000', '@level': '1', '@name': '神奈川県'}, {'@code': '15000', '@level': '1', '@name': '新潟県'}, {'@code': '16000', '@level': '1', '@name': '富山県'}, {'@code': '17000', '@level': '1', '@name': '石川県'}, {'@code': '18000', '@level': '1', '@name': '福井県'}, {'@code': '19000', '@level': '1', '@name': '山梨県'}, {'@code': '20000', '@level': '1', '@name': '長野県'}, {'@code': '21000', '@level': '1', '@name': '岐阜県'}, {'@code': '22000', '@level': '1', '@name': '静岡県'}, {'@code': '23000', '@level': '1', '@name': '愛知県'}, {'@code': '24000', '@level': '1', '@name': '三重県'}, {'@code': '25000', '@level': '1', '@name': '滋賀県'}, {'@code': '26000', '@level': '1', '@name': '京都府'}, {'@code': '27000', '@level': '1', '@name': '大阪府'}, {'@code': '28000', '@level': '1', '@name': '兵庫県'}, {'@code': '29000', '@level': '1', '@name': '奈良県'}, {'@code': '30000', '@level': '1', '@name': '和歌山県'}, {'@code': '31000', '@level': '1', '@name': '鳥取県'}, {'@code': '32000', '@level': '1', '@name': '島根県'}, {'@code': '33000', '@level': '1', '@name': '岡山県'}, {'@code': '34000', '@level': '1', '@name': '広島県'}, {'@code': '35000', '@level': '1', '@name': '山口県'}, {'@code': '36000', '@level': '1', '@name': '徳島県'}, {'@code': '37000', '@level': '1', '@name': '香川県'}, {'@code': '38000', '@level': '1', '@name': '愛媛県'}, {'@code': '39000', '@level': '1', '@name': '高知県'}, {'@code': '40000', '@level': '1', '@name': '福岡県'}, {'@code': '41000', '@level': '1', '@name': '佐賀県'}, {'@code': '42000', '@level': '1', '@name': '長崎県'}, {'@code': '43000', '@level': '1', '@name': '熊本県'}, {'@code': '44000', '@level': '1', '@name': '大分県'}, {'@code': '45000', '@level': '1', '@name': '宮崎県'}, {'@code': '46000', '@level': '1', '@name': '鹿児島県'}, {'@code': '47000', '@level': '1', '@name': '沖縄県'}] #都道府県のマッピング convert_rules_dict = {} for rule in todohuken: convert_rules_dict.update({rule['@code'] : rule['@name']}) df['area'] = df['area'].map(convert_rules_dict) #市区町村等のいらないものを削除 df = df.dropna() |
ここでデータフレームの最初を確認すると・・・
1 |
df.head() |
とでてくる。データ確認!よかった(小保方感
3. データ整形-ロケーション情報をデータフレームに入れ込む
これで、都道府県と人口増減データがデータフレーム化できた。ただ、これにロケーションデータが紐づいていないと、ヒートマップ表示ができない。誰か、僕じゃない誰かが「都道府県と緯度経度のデータ」なんかをCSV化してくれてないかなと思ったが、見つけられなかった。仕方なく、色々なコピーなどを行ってCSVを自分で作成。
CSVデータはGithubに同じくあげてるので、なんかの機会あれば使ってください。
1 2 3 4 5 6 |
df2 = pd.read_csv('/Users/matsuzakiyousuke/tespy/todohuken_geo.csv') todohuken_data_geo = pd.merge(df, df2, left_on='area', right_on='都道府県') del todohuken_data_geo['No'], todohuken_data_geo['area'] todohuken_data_geo.head() |
都道府県の人口増減数と緯度経度のデータがひもづきました。データ確認!よかった。
地図上に何かしらを表示してみる
1 2 3 4 5 6 7 |
%matplotlib inline import folium todohuken_map = folium.Map(location=[todohuken_data_geo['緯度'].mean(), todohuken_data_geo['経度'].mean()], zoom_start=5) todohuken_map |
まずJupyter用に%matplotlib inline宣言して、インライン表示できるように。foliumもインポート。さっきのデータフレーム上の緯度経度それぞれの平均値をfolium.Mapの引数に、zoom_startを5に設定してみます。
なんもない地図が表示されました。デザイン的にもこなれてていい感じ。
寄り道①県庁所在地にマーカーを表示
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
#緯度・経度のタプルが作りたかったが良い方法わからず。力技感 coordinates = [] keido = list(todohuken_data_geo['経度']) ido = list(todohuken_data_geo['緯度']) for k, i in zip(keido, ido): coordinates.append((i, k)) #マーカー追加していく for i in range(0,len(coordinates)): folium.Marker(coordinates[i], ).add_to(todohuken_map) todohuken_map |
folium.Makerにcoordinatesっていう緯度経度のリストを渡して、add_toメソッドでtodohuken_mapへ渡してます。GoogleMapとはまた違う風合いのマーカー表示でできあがりました。
寄り道②県庁所在地をヒートマップ表示
もう少し寄り道するとして、マーカー表示でなくて、ヒートマップ表示ならどうなるのか?
1 2 3 4 5 6 7 8 |
from folium.plugins import HeatMap # initialize map todohuken_map = folium.Map(location=[todohuken_data_geo['緯度'].mean(), todohuken_data_geo['経度'].mean()], zoom_start=5) # add heat todohuken_map.add_child(HeatMap(coordinates)) todohuken_map |
ヒートマップの意味を考えると「?」ですが、情報が密(=県庁所在地同士が近い)な地域は赤くなってます。
人口増減を元にヒートマップ化
1 2 3 4 5 6 7 8 |
coordinates_plus = [] keido = list(todohuken_data_geo['経度']) ido = list(todohuken_data_geo['緯度']) increace = list(todohuken_data_geo['increace']) for k, i, ic in zip(keido, ido, increace): coordinates_plus.append((i, k, float(ic))) |
緯度、経度、人口増減をそれぞれリスト化。またその数値群をタプル化して、リストに入れてきます。FoliumのHeatMapクラスをインスタンス化する際の1つ目、2つ目を緯度・経度に、3つ目をヒートマップ色が紐づくデータにするようです。(自信ない、誤読してるかも)
1 2 3 4 5 6 |
# initialize map todohuken_map = folium.Map(location=[todohuken_data_geo['緯度'].mean(), todohuken_data_geo['経度'].mean()], zoom_start=5) # add heat todohuken_map.add_child(HeatMap(coordinates_plus, radius=12)) todohuken_map |
最後に、ヒートマップ化。日本の政令指定都市がかろうじて赤いか?というような地図ができました。東京だけ真っ赤ですね。今回指定してないですが、[gradient(色のグラデーション)][min_opacity][max_val]などなどパラメータがあるようです。最後のデザイン気にする場合は指定するとよいかと思います。