はじめに
@kohei-otaさんの記事[1]に感銘を受け、自分もGTFS Realtimeデータを使ってみたいと思い。バスの1日の動きの可視化に取り組んでみました。
可視化の対象としたのは私が高校時代によく乗っていた新潟バス会社である越後交通と新潟交通の2社です。
用いたデータ
GTFSデータとは何か?というところについては@kohei-otaさんの記事を
参考にしていただくとして、今回は以下のデータを対象としました。
- 対象バス:越後交通 (越後交通HP)
新潟交通 (新潟交通HP) - 対象データ:[2]で公開されているVehiclePositionのGTFS Realtimeデータ
- 期間:2023年11月29日
- 可視化ツール:Mobmap [3]
アニメーション化した結果
上記2社でhttps://loc.bus-vision.jp/toki-liner/view/opendataNiigata.htmlで公開されているGTFS Realtimeデータの路線は各社2~3路線ぐらいのようでして、新潟-長岡-柏崎-上越を結ぶ路線しか表示できていません。本当はもっと多くのバスが運行されているものと思います。
手順
越後交通と新潟交通のバスが動く様子を前述のようにアニメーションするために以下の手順を踏みました。
1. データ取得
https://loc.bus-vision.jp/toki-liner/view/opendataNiigata.htmlで公開されているGTFS Realtimeデータ(.binファイル)を5分毎に取得しローカルPCに蓄積しました。
2. データ処理
.binファイルを蓄積したのと同じディレクトリにMobmapにアップロードできる形式のcsvファイルを作成するpythonコードを作成しました。
バスのidについては越後交通と新潟交通のidが重複してしまうことがありましたので、越後交通にidには元のidに50を足し、新潟交通のidには元のidに130足した数にしています。
import os
import pandas as pd
import pytz
from google.transit import gtfs_realtime_pb2
def read_bin_file(file_path, initial_letter):
# GTFS Realtimeデータの読み込み
feed = gtfs_realtime_pb2.FeedMessage()
with open(file_path, 'rb') as file:
feed.ParseFromString(file.read())
# データの抽出
data_list = []
for entity in feed.entity:
if entity.HasField('vehicle'):
vehicle = entity.vehicle
# 頭文字に基づいた数値を追加
if initial_letter == 'e':
id_suffix = 50
if initial_letter == 'n':
id_suffix = 130
vehicle_id = id_suffix + int(vehicle.vehicle.id) # 頭文字を追加
data_list.append({
'id': vehicle_id,
'timestamp': vehicle.timestamp,
'latitude': vehicle.position.latitude,
'longitude': vehicle.position.longitude
})
return data_list
def main():
directory_path = '.' # ファイルが存在するディレクトリのパス
bin_files = [f for f in os.listdir(directory_path) if f.endswith('.bin')]
# ファイル名に基づいて時系列順にソート
bin_files.sort()
all_data = []
for file in bin_files:
file_path = os.path.join(directory_path, file)
initial_letter = file[0] # ファイル名の頭文字を取得
file_data = read_bin_file(file_path, initial_letter)
all_data.extend(file_data)
# DataFrameに変換
df = pd.DataFrame(all_data)
# UNIXtimestampを日時に変換
japan_timezone = pytz.timezone('Asia/Tokyo')
df['timestamp'] = pd.to_datetime(df['timestamp'], unit='s').dt.tz_localize(pytz.utc).dt.tz_convert(japan_timezone)
# 時系列順にソート
df.sort_values('timestamp', inplace=True)
# CSVファイルに保存(既存のデータに追加)
df.to_csv('gtfs_realtime_data.csv', mode='a', header=False, index=False)
if __name__ == "__main__":
main()
3. Mobmap Webに読み込み
2.で作成したcsvファイルをMobmap Webの使い方で公開されている方法に従いcsvファイルをMobmap Webにアップロードするだけで簡単にアニメーション化できました。特に私がここで解説する必要もないぐらいの手軽さでした。
考察と課題
公開されている路線がそうなだけかもしれませんが、新潟県の主要都市である新潟市と長岡市を結ぶバスが比較的多く行き来していることが観察されました。また燕市-新潟市の間だけバスが他と比べると速く動いている様子がみられますので、この間はバス停が少ないのかなと考えられます。
本記事の課題としては以下が挙げられます。
-
可視化した路線が少なく、かつ長距離の路線だけなので新潟県全体を見るような広範囲での可視化になっている。そのため新潟市内、長岡市内での動きが十分に可視化できていない。
-
バスの位置情報だけの可視化なので、運行状態の可視化をしていない。(GTFS Realtimeデータを使いこなせていないということ)
今後これらの課題に取り組んでいきたいとも思っていますが、長距離路線ではなくコミュニティバスが街中を縫うようにして動いていくことを可視化することも検討しています。これにより、より興味深いデータが得られるかもしれません。
👆新潟県燕市のコミュニティバスの1日の動きを可視化してみるの記事にてコミュニティバスの動きについて可視化してみました。
参考サイト
[1] 熊本のバス5社のGTFS Realtimeオープンデータを使う
[2] https://loc.bus-vision.jp/toki-liner/view/opendataNiigata.html
[3] Mobmap Webリンク