14
18

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

MYJLabAdvent Calendar 2019

Day 21

【foliumで可視化】近年ファミマ増えすぎな気がする

Last updated at Posted at 2019-12-21

これはMYJLab Advent Calendar 2019の21日目の記事です。サッチーが担当いたします。(遅れてすみませんでした)

今回は

すること

最近道路を挟んで向かい側同士にファミリマートがある、みたいな現象が私の地元では起きています。この現象を可視化すべく、今回はファミリーマートの店舗数の増加を都道府県ごとに時系列ヒートマップに落としてみようと思います。

使うもの

LeafletというJavaScriptでいい感じのマップを描画できるライブラリがあります。今回はPythonでLeafletを使うことができるようにしてくれるfoliumというライブラリを使って時系列ヒートマップを作成します。

早速描く

実行環境

  • Jupyter Notebook
  • Python 3.7.3
  • folium 0.10.1

foliumはバージョンによって機能や使い方がかわってくるので、今回は必ずバージョンを0.10.1にするようにしてください。

# ライブラリ読み込み
import pandas as pd
import folium
from folium import plugins

データ準備

こちらのサイトにあった1999年から2019年のファミリーマートの都道府県ごとの店舗数をcsvファイルにし直してデータを用意しました。PythonのRequestsで落とせるようにしてあります。また、地図に描画するにあたって各県の緯度経度が必要です。今回は都道府県庁が存在する場所を各県の緯度経度とします。データはこちらからダウンロードできます。

# 店舗数のデータ
import requests
import io

URL = "https://drive.google.com/uc?id=1-8tppvHwwVJWufYVskTfGz7cCrBIE0SM"
r = requests.get(URL)
famima_data = pd.read_csv(io.BytesIO(r.content))
famima_data.head()
スクリーンショット 2019-12-21 15.22.03.png

近年増えているというだけあって、1999~2006年はかなり欠損値が多くなっています。

# 都道府県庁の緯度経度
geo_data = pd.read_csv("./data/prefecturalCapital.csv")
geo_data.head()
スクリーンショット 2019-12-21 15.29.01.png

次に、この2つのデータフレームを結合します。idをキーにして結合したいので、geo_dataのidを0始まりに直して結合します。欠損値は一旦0とします。

import numpy as np

geo_data.id = geo_data.id - 1
merged_data = pd.merge(famima_data, geo_data[["id", "lat", "lon"]], on=["id"])
merged_data = merged_data.replace(np.nan, 0)
merged_data.head()
スクリーンショット 2019-12-21 18.02.45.png

基本のデータの準備ができました。

増加のデータに変換していく

今回は店舗数の増減の推移を可視化したいので列で差分をとります。

# 時系列のカラム名の配列を取得する
time_columns = merged_data.columns[2:23].values

# 店舗数のデータの部分のみ差分をとり、diff_dataとする
merged_data.loc[:, time_columns] = merged_data.loc[:, time_columns].astype(float)
diff_data = merged_data.copy()
diff_data.loc[:, time_columns]  = merged_data.loc[:, time_columns].diff(axis=1)

# 1999年のデータがなくなるので削除する
diff_data = diff_data.dropna(axis=1)
time_columns = time_columns[1:]

diff_data.head()
スクリーンショット 2019-12-21 19.06.26.png

差分が取れたらmin-max-scalingをします。foliumのヒートマップでは0があるとなにかと不都合なので、全体に1e-4を足します。

# diff_dataをスケーリングし、scaled_dataとする
scaled_data = diff_data.copy()

scaled_data.loc[:, time_columns] = (diff_data.loc[:, time_columns] - diff_data.loc[:, time_columns] .min().min()) / (diff_data.loc[:, time_columns] .max().max() - diff_data.loc[:, time_columns] .min().min())
scaled_data.loc[:, time_columns] = scaled_data.loc[:, time_columns] + 1e-4
scaled_data.head()
スクリーンショット 2019-12-21 19.11.27.png

最後に、時系列ヒートマップを描画するために
[[[緯度, 経度, データ] * 47都道府県] * 1999~2019]となる3次元データを作成します。

heat_map_data = [[[row['lat'],row['lon'], row[idx]] for index, row in scaled_data.iterrows()] for idx in time_columns]

# データの形がわかりにくいので一つ目だけ出力
heat_map_data[0]
#出力
[[43.064359, 141.347449, 0.051760516605166056],
 [40.824294, 140.74005400000001, 0.051760516605166056],
 [39.70353, 141.15266699999998, 0.05545055350553506],
 [38.268737, 140.872183, 0.060985608856088565],
 [39.718175, 140.10335600000002, 0.051760516605166056],
 [38.240127, 140.362533, 0.07390073800738008],
 [37.750146, 140.466754, 0.0923509225092251],
 [36.341817, 140.446796, 0.04807047970479705],
 [36.56575, 139.883526, 0.05545055350553506],
 [36.391205, 139.060917, 0.060985608856088565],
 [35.857771, 139.647804, 0.060985608856088565],
 [35.604563, 140.123179, 0.04807047970479705],
 [35.689184999999995, 139.691648, 0.0997309963099631],
 [35.447505, 139.642347, 0.06467564575645757],
 [37.901699, 139.022728, 0.051760516605166056],
 [36.695274, 137.211302, 0.06467564575645757],
 [36.594729, 136.62555, 0.06467564575645757],
 [36.065220000000004, 136.221641, 0.06283062730627306],
 [35.665102000000005, 138.568985, 0.05545055350553506],
 [36.651282, 138.180972, 0.051760516605166056],
 [35.39116, 136.722204, 0.05729557195571956],
 [34.976987, 138.383057, 0.05729557195571956],
 [35.180246999999994, 136.906698, 0.07574575645756458],
 [34.730546999999994, 136.50861, 0.06836568265682658],
 [35.004532, 135.868588, 0.05360553505535055],
 [35.020996200000006, 135.7531135, 0.05360553505535055],
 [34.686492, 135.518992, 0.0978859778597786],
 [34.69128, 135.183087, 0.08128081180811808],
 [34.685296, 135.832745, 0.04622546125461255],
 [34.224806, 135.16795, 0.08866088560885609],
 [35.503463, 134.238258, 0.051760516605166056],
 [35.472248, 133.05083, 0.051760516605166056],
 [34.66132, 133.934414, 0.060985608856088565],
 [34.396033, 132.459595, 0.06836568265682658],
 [34.185648, 131.470755, 0.051760516605166056],
 [34.065732000000004, 134.559293, 0.051760516605166056],
 [34.340140000000005, 134.04297, 0.051760516605166056],
 [33.841649, 132.76585, 0.051760516605166056],
 [33.55969, 133.530887, 0.051760516605166056],
 [33.606767, 130.418228, 0.060985608856088565],
 [33.249367, 130.298822, 0.05360553505535055],
 [32.744541999999996, 129.873037, 0.10526605166051661],
 [32.790385, 130.742345, 0.06652066420664207],
 [33.2382, 131.612674, 0.05914059040590406],
 [31.91109, 131.423855, 0.05729557195571956],
 [31.560219, 130.557906, 0.0868158671586716],
 [26.211538, 127.68111499999999, 0.07759077490774909]]

いざ描画

japan_map = folium.Map(location=[35, 135], zoom_start=6)
hm = plugins.HeatMapWithTime(heat_map_data, index=list(time_columns),auto_play=False,radius=30,max_opacity=1,gradient={0.1: 'blue', 0.25: 'lime', 0.5:'yellow',0.75: 'orange', 0.9:'red'})
hm.add_to(japan_map)

japan_map

画面収録-2019-12-21-19.37.12.gif

約0.052以下がマイナスを取っているはずなので増分のみが可視化されています。

動く地図うれしい・・・!!!

ざつ目に考察

  • 2010年くらいまではそんなに増加していない(やはり近年の増加傾向にある)
  • 2010年以降は増加が見られるが大きい都市がある都道府県ばかり
  • 地方はそんなに増えていない

終わり

そんなにコードを書かずに時系列ごとのデータの推移を可視化できるのはとても便利だと思いました。なんかもっと有意義なことに使いたいものです。最後までお読みいただきありがとうございました。訂正箇所とうあればコメントをしていただけると幸いです。

参考,出所

14
18
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
14
18

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?