- 「PythonでGoogle Maps APIを用いて車通勤時間を調べたい人」に向けた記事です。
- 複数の出発点から目的地までの所要時間・移動距離を調べるのに便利です。
- matplotlibで可視化も容易です。
- 転職活動や住居探しの参考に役立ちます!
コード
ライブラリインポート、変数・関数定義
#%%
import numpy as np
import matplotlib.cm as cm
import matplotlib.pyplot as plt
plt.rcParams["font.family"] = "MS Gothic"
import requests
#%%
def ido_keido(ido,keido):
return str(ido) + "," + str(keido)
# %%
def map(origin, destination):
API_KEY = "" # APY KEYを適宜入れてください
url = "https://maps.googleapis.com/maps/api/directions/json?"\
+f"origin={origin}&"\
+f"destination={destination}&"\
+f"departure_time=now&"\
+f"key={API_KEY}"
res = requests.get(url)
result = res.json()
if result['status'] == 'OK':
routes = result["routes"][0]
legs = routes["legs"][0]
distance = legs["distance"]["value"]/1000 # km
duration = legs["duration_in_traffic"]["value"]/60 # min #departure_time=nowによる現在の情報
#duration = legs["duration"]["value"]/60 # min # 時間によらない情報
return distance,duration
else:
print(f"ルートが見つかりませんでした。")
return None
関数map(origin, destination)
は出発地、目的地を引数にとって、移動距離と所要時間を返す関数です。
出発地、目的地は日本語でOKです。
また、関数ido_keido(ido,keido)
により緯度・経度をmap()
の引数にすることもできます。
(次のセクションで例を出します)
ここでは、変数urlにdeparture_time=now
をつけ、またlegs["duration_in_traffic"]["value"]/60
として、duration_in_traffic
を指定することで現時点での情報を取得し、返しています。
時間によらない結果が欲しい場合は、legs["duration"]["value"]/60
とすればOKです。
(+f"destination={destination}&"\
の行をコメントアウトしても構いません)
※Google Maps APIの登録については外部関連サイトを参照ください。
動作テスト
さっそく使ってみましょう。
ここでは名古屋市のマンションからデンソーまでの距離と時間を取得してみます。
origin = "プレミスト泉レジデンス"
destination= "デンソー先端技術研究所"
distance,duration = map(origin, destination)
print(distance,duration)
#(19.332, 30.85) # 移動距離(km), 所要時間(min)
google mapで手動で取得したものと同じ結果が得られました。
手動もスクリプトもdeparture_time=now
で現時点の情報を取得しているためです。
関数ido_keido(ido,keido)
を用いると緯度・経度を直接指定することもできます。
位置が微妙にずれてますがほぼ同じ結果になります。
#%%
map(ido_keido(35.176825, 136.915061), ido_keido(35.123035, 137.075654))
# (19.417, 29.9) # 移動距離(km), 所要時間(min)
複数の出発点を調べてプロット
出発地点を複数用意して、それぞれの結果をプロットしてみます。
for文を使って各出発点の移動距離・所要時間をリストlist_dist, list_duraに入れるスクリプトです。
#%%
origins = ["プレミスト泉レジデンス",
"プラウドタワー覚王山",
"プラウド一社パークフロント",
"グランドメゾン桜山菊園町",
"グランドメゾン熱田の杜C棟",
"プラセシオン徳重"
"ソフィア共和 ",
]
destination= "デンソー先端技術研究所"
#%%
list_dist = []
list_dura = []
for origin in origins:
distance,duration = map(origin,destination)
list_dist.append(distance)
list_dura.append(duration)
結果をいくつかプロットしてみましょう。各出発点の所要時間を棒グラフで描きます。
# %%
fig,ax = plt.subplots()
for n, origin in enumerate(origins):
distance,duration = list_dist[n],list_dura[n]
ax.bar(origin,duration, label=origin)
ax.set_ylabel("時間 (min)")
plt.xticks(rotation=35)
移動距離と所要時間をプロットする例です。
#%%
fig,ax = plt.subplots(figsize=(5,5))
for n, origin in enumerate(origins):
distance,duration = list_dist[n],list_dura[n]
ax.scatter(distance,duration, label=origin)
plt.legend(bbox_to_anchor=(1.05, 1),loc='upper left')
ax.set_xlabel("距離 (km)")
ax.set_ylabel("時間 (min)")
ax.set_title(f"{destination}")
地図上にマップしてみる
最後に地図上に所要時間をカラーマップしてみましょう。
外部関連サイトを参考に名古屋の白地図上に結果を重ねます。
# %%
ido1,keido1 = 35.176843, 136.898459
ido2,keido2 = 35.126083, 136.937508
idos = np.linspace(ido1,ido2,5)
keidos = np.linspace(keido1,keido2,5)
#%%
list_dist = []
list_dura = []
for keido in keidos:
for ido in idos:
distance, duration = map(ido_keido(ido,keido), destination)
list_dist.append(distance)
list_dura.append(duration)
# %%
m1 = min(list_dist)
M1 = max(list_dist)
m2 = min(list_dura)
M2 = max(list_dura)
fig,ax = plt.subplots()
from PIL import Image
with Image.open('nagoya.png') as im:
ax.imshow(im, extent=(136.76, 137.09, 34.96, 35.34))
i = 0
for keido in keidos:
for ido in idos:
distance = list_dist[i]
duration = list_dura[i]
sc = ax.scatter(keido,ido,c=duration, marker='s', \
cmap=cm.gnuplot, vmin=m2, vmax=M2)
i += 1
plt.colorbar(sc)
ax.set_xlim(136.85,137)
ax.set_ylim(35.1,35.2)
高速との兼ね合いで、 南東方面の目的地(デンソー 先端技術研究所:愛知県日進市)への所要時間が変わることがわかります。
出発時刻を指定してみる
出発時刻はdeparture_time
にunix時間で指定する必要があります。そこで、冒頭のmap関数を次のように変えてみましょう。
#%%
import numpy as np
import matplotlib.cm as cm
import matplotlib.pyplot as plt
plt.rcParams["font.family"] = "MS Gothic"
import requests
import datetime
import time
#%%
def ido_keido(ido,keido):
return str(ido) + "," + str(keido)
# %%
def map(origin, destination, HH, MM):
d = datetime.datetime(2024, 1, 10, HH, MM, 00)
ut = int(time.mktime(d.timetuple()))
API_KEY = "" # APY KEYを適宜入れてください
url = "https://maps.googleapis.com/maps/api/directions/json?"\
+f"origin={origin}&"\
+f"destination={destination}&"\
+f"departure_time={ut}&"\
+f"key={API_KEY}"
res = requests.get(url)
result = res.json()
if result['status'] == 'OK':
routes = result["routes"][0]
legs = routes["legs"][0]
distance = legs["distance"]["value"]/1000 # km
duration = legs["duration_in_traffic"]["value"]/60 # min #departure_time=nowによる現在の情報
#duration = legs["duration"]["value"]/60 # min # 時間によらない情報
return distance,duration
else:
print(f"ルートが見つかりませんでした。")
return None
時刻を指定しているのが下記のところですね。2024年1月10日HH時MM分00秒ということです。
(※過去は指定できないので適宜変えてください)
d = datetime.datetime(2024, 1, 10, HH, MM, 00)
map関数に出発時刻を指定するための引数HH,MMを追加しました。これで通勤時間の時刻依存性を調べることができます。
試しに、先ほどの複数の出発地について朝6:00から8:30までの通勤時間30分ごとに調べてみましょう。
# %%
list_origin = []
for origin in origins:
list_dist = []
list_dura = []
for HH in [6,7,8]:
for MM in [0,30]:
distance,duration = map(origin,destination, HH,MM)
list_dist.append(distance)
list_dura.append(duration)
list_origin.append((list_dist,list_dura))
# %%
for n,origin in enumerate(list_origin):
duration = origin[1]
plt.plot(duration, label=origins[n], marker="o")
plt.legend(bbox_to_anchor=(1.05, 1),loc='upper left')
横軸が適当になっていますが、1~5は30分刻みで6:00から8:30と読み替えてください。
7:30から8:00(x軸:3~4)に混んで通勤時間10分くらい増えることがわかりますね。
コメント