Python

【Python】鉄道路線をもとに〇駅以内を調べる

はじめに

こちらの記事にもある通り、弊社では福利厚生の一環で「会社から5駅あるいは5km圏内に住んでいれば初期費用を〇〇万円まで会社が負担」という職住近接支援金制度があります。

かくいう私も、入社のための物件探しで不動産仲介の方と「いち、に、さん、し….」と会社近隣の駅から何駅かを調べながらエリアを絞り込みました(高輪ゲートウェイができたせいで行けないエリアがあったりと制約が多かった…)

そこで、ある駅から〇駅以内で行ける範囲を調べる方法を紹介します。

条件

「JR山手線」「京浜東北線」「東京メトロ」「都営線」を利用して「浜松町駅」「大門駅」「芝公園駅」「御成門駅」を出発駅とする

乗り換えの際に駅名が同じもの

  • 対象とする例:大門駅で浅草線→大江戸線に乗り換え
  • 対象としない例:山手線で浜松町駅→(徒歩移動して)大門駅で大江戸線に乗り換え

駅同士が直通していても駅名が異なっていたら別物として扱います。

各駅停車だった場合の途中停車駅の数が〇以内のものを抽出

快速等は考慮しません

使用データ

今回は駅データ.jp様 が提供しているデータを活用します。利用したデータは以下の通りです。

  • 駅データ
  • 接続駅データ

各データを前処理したものの例は以下の通りです。

駅データ(station_gri)

station_id station_name lon lat
1130203 目黒 139.715775 35.633923
1162915 三田 135.229790 34.888787
2800917 白金高輪 139.734104 35.642903
2800918 白金台 139.726133 35.637917
9930305 芝公園 139.749824 35.654074

駅接続データ(u_conn_gri)

line_id station_id1 station_id2 station_name1 station_name2 line_name
99304 9930416 9930417 東大島 船堀 都営新宿線
99304 9930417 9930418 船堀 一之江 都営新宿線
99304 9930418 9930419 一之江 瑞江 都営新宿線
99304 9930419 9930420 瑞江 篠崎 都営新宿線
99304 9930420 9930421 篠崎 本八幡 都営新宿線

 

ネットワーク可視化

networkxというpythonのライブラリを利用します。こちらはデータをグラフ構造で扱うことができるもので、駅情報をノードで、駅の接続情報をエッジで表現します。

ネットワークの可視化をしてみます

imprt networkx as nx

G = nx.Graph()
G.add_edges_from(conn_gri[["station_name1","station_name2"]].values.tolist())

plt.figure(figsize=(15,15))

pos = nx.spring_layout(G)
nx.draw(G, node_color='lightblue', with_labels = True,font_family='IPAexGothic')
plt.axis("off")
plt.show()

可視化結果は次のようになりました。

ぐちゃぐちゃですが、やりたいことは実現できているように見えます(浅草線西馬込駅から判断)

 

〇駅以内の駅取得

幅優先探索によって所定回数以内エッジを通って行くことのできるノードを取得します。

アルゴリズムはnetworkxの探索の機能を呼び出すだけです。便利!

実験のため大門駅から2駅以内で行ける範囲を取得します

list(nx.bfs_edges(G,source="大門",depth_limit = 2))
"""出力
[('大門', '汐留'),
 ('大門', '赤羽橋'),
 ('大門', '三田'),
 ('大門', '新橋'),
 ('汐留', '築地市場'),
 ('赤羽橋', '麻布十番'),
 ('三田', '泉岳寺'),
 ('三田', '白金高輪'),
 ('三田', '芝公園'),
 ('新橋', '東京'),
 ('新橋', '品川'),
 ('新橋', '有楽町'),
 ('新橋', '浜松町'),
 ('新橋', '銀座'),
 ('新橋', '虎ノ門'),
 ('新橋', '東銀座')]
"""

一覧を取得することができました!浅草線・大江戸線・新宿線等が該当していることがわかります。

5駅以内のエリアを抽出

最後に「浜松町駅」「大門駅」「芝公園駅」「御成門駅」から5駅以内の駅を一覧で確認します。

station_list = []
start_stations = ["浜松町","大門","芝公園","御成門"]

for x in start_stations:
    station_list += list(nx.dfs_preorder_nodes(G, source=x, depth_limit=5))
list(set(station_list)-set(start_stations))

"""出力
['汐留',
 '桜田門',
 '溜池山王',
 '永田町',
 '外苑前',
 '国立競技場',
 '大崎',
 '六本木',
 '三田',
 '品川',
 '恵比寿',
 '勝どき',
 '赤坂見附',
 '赤羽橋',
 '泉岳寺',
 '内幸町',
 '銀座',
 '月島',
 '秋葉原',
 '淡路町',
 '戸越',
 '大手町',
 '六本木一丁目',
 '神保町',
 '日本橋',
 '有楽町',
 '霞ケ関',
 '築地市場',
 '東銀座',
 '豊洲',
 '末広町',
 '銀座一丁目',
 '門前仲町',
 '竹橋',
 '三越前',
 '日比谷',
 '京橋',
 '新橋',
 '高輪台',
 '神谷町',
 '虎ノ門',
 '表参道',
 '国会議事堂前',
 '青山一丁目',
 '広尾',
 '白金台',
 '麹町',
 '目黒',
 '大井町',
 '五反田',
 '新御茶ノ水',
 '半蔵門',
 '虎ノ門ヒルズ',
 '大森',
 '白金高輪',
 '麻布十番',
 '神田',
 '赤坂',
 '高輪ゲートウェイ',
 '二重橋前',
 '東京',
 '田町',
 '四ツ谷',
 '新富町']
"""

一通りの列挙ができていることがわかります

おわりに

今回は路線をネットワークに見立てて〇駅以内を抽出する手法について紹介しました。

費用や時間、出発時刻(この場合は有向グラフになる)等の情報を追加していくことでより実用的に使えるようになるのではないかと思います。

 

 

sato
データサイエンス事業部所属 寒さと生活が苦手