人流分析
- SoftWareDesign (2020年4月号)に、興味をそそる記事があり試してみました。
- Jupyter Notebook上で、疑似人流分析データをマップ表示させる
疑似人流データの取得
仮想環境構築
ipyleaflet
numpy
pandas
matplotlib
csvファイルを読み込んで、1件のデータを表示
import numpy as np
import pandas as pd
import datetime as dt
df = pd.read_csv('2013_12_24.csv')
df.iloc[:,2] = pd.to_datetime(df.iloc[:,2])
df.iloc[:,4] = df.iloc[:,4].astype(float)
df.iloc[:,3] = df.iloc[:,3].astype(float)
print( df.iloc[ 1, : ] )
出力結果
uid 1
gender 1
timestamp 2013-12-24 01:00:00
lat 35.1707
lon 136.882
cat1 travel
cat2 Train Station
STAY_MOVE STAY
cat_id 2
Name: 1, dtype: object
ある期間の人流データを取得
humans = df[(dt.datetime(2013, 12, 24, 7, 0) < df.iloc[:,2]) &
(df.iloc[:,2] < dt.datetime(2013, 12, 24, 9, 0))]
print(humans)
出力結果
uid gender timestamp lat lon cat1 \
74 1 1.0 2013-12-24 07:05:00 35.170274 136.880557 NaN
75 1 1.0 2013-12-24 07:10:00 35.170274 136.880554 NaN
76 1 1.0 2013-12-24 07:15:00 35.170273 136.880552 NaN
... ... ... ... ... ... ...
140842 1467 NaN 2013-12-24 08:45:00 35.483186 137.519981 NaN
140843 1467 NaN 2013-12-24 08:50:00 35.485364 137.516451 NaN
140844 1467 NaN 2013-12-24 08:55:00 35.487892 137.512969 NaN
cat2 STAY_MOVE cat_id
74 NaN MOVE NaN
75 NaN MOVE NaN
76 NaN MOVE NaN
... ... ... ...
140842 NaN MOVE NaN
140843 NaN MOVE NaN
140844 NaN MOVE NaN
[8946 rows x 9 columns]
緯度、経度、ズームサイズ、ベースマップを指定してマップ表示
from ipyleaflet import *
from ipyleaflet import Map, FullScreenControl
center = (35.1707, 136.882)
m = Map(center=center, zoom=15, basemap=basemaps.OpenStreetMap.Mapnik)
m
「人の位置」をマップに表示
points = []
for row in humans.itertuples(name=None):
points.append(Circle(location=(row[4], row[5]),radius=150, fill=True, fill_opacity=0.3, stroke=False))
for point in points:
m.add_layer(point)
m
特定の人物の移動した経路をアニメーション表示
aPerson = df[df.iloc[:,0]==1015]
locs = []
ant_paths = []
for row in aPerson.itertuples(name=None):
locs.append([row[4], row[5]])
ant_paths.append(AntPath(locations=locs, use='polyline'))
m += ant_paths[-1]
特定条件に応じた「人々の位置頻度分布」の重ね合わせ表示
%matplotlib inline
import matplotlib.pyplot as plt
# 人の存在頻度を描画する、緯度経度範囲を定義
right = max(humans.iloc[:,4])
left = min(humans.iloc[:,4])
top = max(humans.iloc[:,3])
bottom = min(humans.iloc[:,3])
# 人の存在頻度を2Dヒストグラムとして描く
plt.figure( figsize=(15, 15), dpi=500 )
fig, ax = plt.subplots( figsize=(5, 5), dpi=100 )
ax.hist2d( humans.iloc[:,4], humans.iloc[:,3],
bins=[ np.linspace( left, right, 200 ),
np.linspace( bottom, top, 200 )],
cmap=plt.cm.jet )
ax.grid( False ); ax.axis('off')
# matplotlibレンダリング結果を画像(image)に格納
fig.canvas.draw()
image = np.array( fig.canvas.renderer._renderer )
# Python 2と3で、ストリームを扱うモジュールが
# 違うため、それぞれに応じたストリーム定義にする
from base64 import b64encode; import PIL
try:
from StringIO import StringIO
py3 = False
except ImportError:
from io import StringIO, BytesIO
py3 = True
if py3:
f = BytesIO()
else:
f = StringIO()
# 作成した2次元画像を、地図に重ねて描画する準備
im = PIL.Image.fromarray( image ); im.save( f, 'png' )
data = b64encode( f.getvalue() )
if py3:
data = data.decode( 'ascii' )
imgurl = 'data:image/png;base64,' + data
bounds = [ (bottom, left), (top, right) ]
io = ImageOverlay( url=imgurl, bounds=bounds )
m.add_layer( io ) # 画像をレイヤーに追加
io.interact( opacity=( 0.0, 1.0, 0.01) ) # 透明度を可変にする
おわりに
- どこかのサイトで混雑状況をマップ表示していたのを見て気になっていたので、すっきりした。
- SoftWare Designは、ITエンジニアにとって有用な記事が多いので、おすすめ。
amzn.to