アクトインディ開発者ブログ

子供とお出かけ情報「いこーよ」を運営する、アクトインディ株式会社の開発者ブログです

Colaboratory + Foliumで地図マッピングしてみる

morishitaです。
Alexa スキル「いこーよのおでかけナビ」では、ユーザの自宅を起点に探したお出かけ先を提案します。

いこーよのおでかけナビ

いこーよのおでかけナビ

東京ではたくさんの施設を紹介できますが、そうでない地域もあります。
一応、人口の多い都市ではどれくらいの紹介できる施設の母数があるか確認して、検索範囲や条件を調整しています。

しかし、やはり全国的な施設の分布を感覚知として知っておきたくなり、やってみました。

地図へのマッピング

各施設の緯度経度はわかっているので、それを地図上にマッピングしてみようと思いました。

最初に手っ取り早い手段として、Google マイマップを使ってみました。
やってみてわかったのですが、マイマップは1レイヤー 2,000 ポイントしか登録できないようです。 2,000 件毎に作業を繰り返すにはデータが多かったので別の手段を探すことにしましした。

Leafletを使って HTML と JS でサクッとできるかなとも思ったのですが、 Colaboratory + Folium を使ってもできそうだ思い、どうせならやってみたことがないものでやってみることにしました。

Folium とは?

foliumは Python のライブラリで、Leafletを使ってデータを地図上に可視化できます。
これを Colaboratory 上で使うと、Python 側で作った座標を持ったデータを地図上に簡単にマッピングできます。

Colaboratory + folium をやってみる。

Google Drive 上のスプレッドシートに可視化したいデータを用意します。
それを読み込んで folium で表示した地図上にマーカーとして表示します。

スプレッドシートの読み込み

最初にお決まりの手順、次の2行で Google アカウントの認証を通します。

from google.colab import auth
auth.authenticate_user()

続いて、次のコードで認証されたgspreadオブジェクトを取得します。

!pip install gspread
import gspread
from oauth2client.client import GoogleCredentials

gc = gspread.authorize(GoogleCredentials.get_application_default())

そして次のコードで値を読み取って DataFrameに格納します。
一旦文字列として値を読み込んでしまうので、最後にfloatに変換しています。

spreadsheet_key = '<スプレッドシートのID>'
worksheet = gc.open_by_key(spreadsheet_key).sheet1
table = worksheet.get_all_values()

import pandas as pd
df = pd.DataFrame(table[1:], columns=table[0])
df = df.astype({'id': int, 'lat': float, 'lng': float}) # 型の変換

ここまでで、スプレッドシートからのデータの読み出しは終了。

地図へのマッピング

次のコードだけで、地図を表示して、読み込んだデータをマーカーとしてマッピングしてくれます。

!pip install folium
import folium
m = folium.Map(location=[35.681382, 139.76608399999998], zoom_start=5) #東京駅の緯度経度

for index, data in df.iterrows():
  folium.Marker(location=[data["lat"], data["lng"]]).add_to(m)
m

簡単ですね。

しかし、重い

いこーよの登録施設全部を読み込もうとしました。
スプレッドシートの読み込みは問題ないのですが、地図にマッピングしようとしても一向に表示されません。

データが多すぎるのかなぁと思い、データを間引いて 3,000 件くらいに絞り込んだら、なんとか待っていられる時間に地図が表示されるようになりました。
ただ、表示されるだけでズームやスクロールはまともに動きません。

f:id:HeRo:20180920093710p:plain

1,500 くらいまで減らして、もっさりした動作ですがなんとかズームやスクロールができる状況です。

登録施設が全国に分布しているのはわかります。
わかるけど、そもそも、3,000だの1,500だの、そんな小さい数に間引いたデータを可視化したかったのではないのです。
だいたい、Google マイマップの1レイヤーより少ないやん。

MarkerCluster

folium には Leaflet.markerclusterも組み込まれていることがわかりました。 これで表示するマーカーを減らしてやれば少しはマシにならないかなと思ってやってみました。

f:id:HeRo:20180927205154g:plain

しかし、やっぱり 3,000 件くらいまで減らさないと初期表示で待っていられないほど時間がかかるというのは変わりませんでした。

leaflet を使う限り自分で実装しても変わらないだろうなぁ。

まとめ

  • Colaboratory で Google スプレッドシートを読み込むのは難しくない
  • Colaboratory + folium で地図マッピングも簡単
  • ただし、3,000 ポイント程度まで

結局、QGISを使って当初の目的を果たしたのでした。

最後に

アクトインディではエンジニアを募集しています。

actindi.net