このぺージではMATLAB Mobileの無料枠の機能を利用して、MATLAB Mobileをiphoneにインストールして、それをもって移動したときのGPSによる位置情報を地図上にプロットするということを行います。
必要なライブラリのインポート
import folium
import json
import pandas as pd
import numpy as np
import geopandas as gpd
import sys
print(sys.version)
print('folium version: 0.12.0')
print(json.__version__)
print(pd.__version__)
print(np.__version__)
print(gpd.__version__)
3.8.12 | packaged by conda-forge | (default, Sep 16 2021, 01:40:49) [MSC v.1916 64 bit (AMD64)] folium version: 0.12.0 2.0.9 1.3.3 1.21.2 0.9.0
GPSデータをプロットする前のベースとなるマップを用意します。folium.Map
を利用して作成することができます
m = folium.Map(location=[35.7056232, 139.751919], # 中心の設定:今回は東京ドーム
tiles='cartodbpositron', # 地図のスタイルを設定
zoom_start = 11, # 初期ズーム率を設定
control_scale = True
)
m # 作成したベースマップを表示
jupyter notebookでは上のマップを表示するためにFile -> trust notebookをクリックしました
読み込みに関しては、open(r'tokyo23.json) -> json.load(f)
の流れで読み込めるらしいのですが、私の環境ではエラーが出てしまったため以下のように読み込みました。そして、私の環境では、データフレームに変換して後のグラデーションの表示(Choropleth図)がうまくいったので
データフレームに変換 -> column名の変更 という作業を行っています
tokyo23_df=gpd.read_file('tokyo23.json')
tokyo23_df = tokyo23_df.rename(columns={'code': 'N03_007'})
tokyo23_df.head(23) #はじめの5行を表示
N03_001 | N03_002 | N03_003 | N03_004 | N03_007 | geometry | |
---|---|---|---|---|---|---|
0 | 東京都 | 台東区 | 13106 | MULTIPOLYGON (((139.76667 35.71330, 139.76609 ... | ||
1 | 東京都 | 杉並区 | 13115 | MULTIPOLYGON (((139.64081 35.66667, 139.64076 ... | ||
2 | 東京都 | 文京区 | 13105 | MULTIPOLYGON (((139.71782 35.71605, 139.71783 ... | ||
3 | 東京都 | 新宿区 | 13104 | MULTIPOLYGON (((139.71397 35.67918, 139.71421 ... | ||
4 | 東京都 | 世田谷区 | 13112 | MULTIPOLYGON (((139.62407 35.61081, 139.62405 ... | ||
5 | 東京都 | 江戸川区 | 13123 | MULTIPOLYGON (((139.85000 35.63841, 139.84999 ... | ||
6 | 東京都 | 墨田区 | 13107 | MULTIPOLYGON (((139.79517 35.70466, 139.79702 ... | ||
7 | 東京都 | 港区 | 13103 | MULTIPOLYGON (((139.71369 35.65800, 139.71367 ... | ||
8 | 東京都 | 豊島区 | 13116 | MULTIPOLYGON (((139.68229 35.72460, 139.68226 ... | ||
9 | 東京都 | 江東区 | 13108 | MULTIPOLYGON (((139.77500 35.61608, 139.77350 ... | ||
10 | 東京都 | 荒川区 | 13118 | MULTIPOLYGON (((139.75833 35.74473, 139.75720 ... | ||
11 | 東京都 | 練馬区 | 13120 | MULTIPOLYGON (((139.56564 35.72166, 139.56568 ... | ||
12 | 東京都 | 葛飾区 | 13122 | MULTIPOLYGON (((139.81667 35.74979, 139.81650 ... | ||
13 | 東京都 | 品川区 | 13109 | MULTIPOLYGON (((139.69539 35.60749, 139.69541 ... | ||
14 | 東京都 | 大田区 | 13111 | MULTIPOLYGON (((139.75000 35.54457, 139.74932 ... | ||
15 | 東京都 | 中野区 | 13114 | MULTIPOLYGON (((139.62500 35.72831, 139.62481 ... | ||
16 | 東京都 | 中央区 | 13102 | MULTIPOLYGON (((139.75833 35.65976, 139.75813 ... | ||
17 | 東京都 | 北区 | 13117 | MULTIPOLYGON (((139.72363 35.73993, 139.72359 ... | ||
18 | 東京都 | 千代田区 | 13101 | MULTIPOLYGON (((139.73150 35.68150, 139.73120 ... | ||
19 | 東京都 | 目黒区 | 13110 | MULTIPOLYGON (((139.68053 35.60445, 139.68045 ... | ||
20 | 東京都 | 渋谷区 | 13113 | MULTIPOLYGON (((139.71128 35.66667, 139.71102 ... | ||
21 | 東京都 | 板橋区 | 13119 | MULTIPOLYGON (((139.67317 35.74768, 139.67325 ... | ||
22 | 東京都 | 足立区 | 13121 | MULTIPOLYGON (((139.81650 35.75000, 139.81650 ... |
strタイプになっていることがわかります。後半ではこのコードによって、その区と人口を紐づけます。
code=tokyo23_df['N03_007'].values
print(code)
code_0=code[0]
print(type(code_0))
['13106' '13115' '13105' '13104' '13112' '13123' '13107' '13103' '13116' '13108' '13118' '13120' '13122' '13109' '13111' '13114' '13102' '13117' '13101' '13110' '13113' '13119' '13121'] <class 'str'>
code_name=pd.read_csv('code_name.csv', encoding="shift-jis")
code_name.head(10)
code | name | |
---|---|---|
0 | 13101 | 千代田区 |
1 | 13102 | 中央区 |
2 | 13103 | 港区 |
3 | 13104 | 新宿区 |
4 | 13105 | 文京区 |
5 | 13106 | 台東区 |
6 | 13107 | 墨田区 |
7 | 13108 | 江東区 |
8 | 13109 | 品川区 |
9 | 13110 | 目黒区 |
name_population=pd.read_csv('name_population.csv', encoding="shift-jis")
name_population.head(10)
name | population | |
---|---|---|
0 | 千代田区 | 61420 |
1 | 中央区 | 157484 |
2 | 港区 | 253940 |
3 | 新宿区 | 343494 |
4 | 文京区 | 227224 |
5 | 台東区 | 203219 |
6 | 墨田区 | 264515 |
7 | 江東区 | 510692 |
8 | 品川区 | 398732 |
9 | 目黒区 | 283153 |
code_nameとname_populationではnameのcolumnが共通しているので、その重複を利用して2つのデータフレームを結合することができます。23区の人口の場合は欠損値はありませんが、データ取得ができておらずNANになっている場合でも how=outer
を利用して結合可能です。
merged_df=pd.merge(name_population, code_name, how='outer')
merged_df.head(10) # 結合したデータフレームの値を確認
name | population | code | |
---|---|---|---|
0 | 千代田区 | 61420 | 13101 |
1 | 中央区 | 157484 | 13102 |
2 | 港区 | 253940 | 13103 |
3 | 新宿区 | 343494 | 13104 |
4 | 文京区 | 227224 | 13105 |
5 | 台東区 | 203219 | 13106 |
6 | 墨田区 | 264515 | 13107 |
7 | 江東区 | 510692 | 13108 |
8 | 品川区 | 398732 | 13109 |
9 | 目黒区 | 283153 | 13110 |
codeとpopulationのみを取り出したデータフレームを作成します
tokyo23_population_df=merged_df.loc[:,['code','population']]
結合したデータフレームの値を確認します
tokyo23_population_df.columns = ['N03_007','population']
tokyo23_population_df.head(10)
N03_007 | population | |
---|---|---|
0 | 13101 | 61420 |
1 | 13102 | 157484 |
2 | 13103 | 253940 |
3 | 13104 | 343494 |
4 | 13105 | 227224 |
5 | 13106 | 203219 |
6 | 13107 | 264515 |
7 | 13108 | 510692 |
8 | 13109 | 398732 |
9 | 13110 | 283153 |
注意:ここではCSVファイルから読み込んだ区のコードは数値として読み込まれているので、
上のセルにあるような文字(str)配列に変更する必要があります
また、自前のデータで行う場合はpopulationに相当する値が文字列として数字が入っている場合は図の作成時にエラーが出てしまうため変換が必要です
tokyo23_population_df['N03_007'] = tokyo23_population_df['N03_007'].astype('str')
tokyo23_population_df.head(10)
N03_007 | population | |
---|---|---|
0 | 13101 | 61420 |
1 | 13102 | 157484 |
2 | 13103 | 253940 |
3 | 13104 | 343494 |
4 | 13105 | 227224 |
5 | 13106 | 203219 |
6 | 13107 | 264515 |
7 | 13108 | 510692 |
8 | 13109 | 398732 |
9 | 13110 | 283153 |
folium.Choroplethという機能を使って作図していきます。以下のように設定を定義します。
folium.Choropleth(geo_data=tokyo23_df, # 地理情報のファイル
name = 'choropleth_tokyo23', # 出力する地図プロットの名前
data = tokyo23_population_df, # 各区の人口データ
columns=['N03_007', 'population'], # 各区の人口データのkey列とその値の列を指定
key_on='feature.properties.N03_007', # keyの情報:feature.properties.xxの形。N03_007の値を基に人口データと紐づける
fill_opacity=0.41, # グラデーションであらわすときの色の濃さを指定
line_opacity=0.1, # 区の境界線の濃さを指定
line_color='blue', # 境界線の色を指定
fill_color='YlGn' # グラデーションのカラーマップを指定
).add_to(m)
folium.LayerControl().add_to(m) # ベースマップmにchoroplethの設定を追加
m
このように23区の人口の多さをグラデーションで示すことができました。次は前半のMATLAB Mobileによりスマートフォンから取得したGPSデータをプロットしていきます。
locations = pd.read_csv("latlon.csv") # 読み込み
numPlot=np.size(locations.Longitude) # データの個数を取得
locations.head(10) # 一部を表示
Latitude | Longitude | |
---|---|---|
0 | 35.69610 | 139.75904 |
1 | 35.69609 | 139.75893 |
2 | 35.69608 | 139.75886 |
3 | 35.69608 | 139.75879 |
4 | 35.69607 | 139.75873 |
5 | 35.69607 | 139.75865 |
6 | 35.69607 | 139.75856 |
7 | 35.69605 | 139.75848 |
8 | 35.69602 | 139.75838 |
9 | 35.69601 | 139.75829 |
folium.vector_layers.PolyLine
を用いてラインを書くことができます
line = folium.vector_layers.PolyLine(
locations=locations,
color='blue',
weight=3)
# マーカーと線の地図レイヤへの追加
m.add_child(line)
GPSデータの最初と最後の座標を取得し、folium.Marker関数でアイコンを表示します
folium.Marker(location=[locations.Latitude[0], locations.Longitude[0]],
icon=folium.Icon(color="red", icon="home")).add_to(m)
folium.Marker(location=[locations.Latitude[numPlot-1], locations.Longitude[numPlot-1]],
icon=folium.Icon(color="red", icon="step-forward")).add_to(m)
m
m.saveを用いてhtlm形式で保存することができます。私の環境ではそのまま開くとうまく見ることができました
m.save('out.html') # 結果の保存
MATLAB Mobileを用いてGPSデータを取得し、MATLAB Online(無料の機能)を用いてCSV形式で保存をしました。そしてpythonのfoliumを用いてその軌跡をプロットすることができました。同様の機能やライブラリを用いて他にもあらゆるタイプのプロットができそうです。
機会があればまた別のプロットの種類も試してみたいと思います。