本記事は国土交通データプラットフォームアドベントカレンダー18日目の記事です。
はじめに
みなさん こんにちは
最近、ニュースでバスの運転手不足の問題についてよく見ます。
- 2023/9/20 NHK バス事業120年 2030年度に運転手3万6000人不足か 背景と今後は
- 2023/10/5 読売新聞 路線バス運転手が足りない…続々と減便・廃止、運転手確保に苦しみ広告で「このままではヤバいです
- 2023/11/13 日本経済新聞 路線バス、運転手足りず廃止 関西は都市路線も
- 2023/12/14 朝日新聞デジタル バス23社「路線廃止を計画」 運転手不足「24年問題」アンケート
バス路線が廃止されると公共交通空白地域が広がり、交通難民が増加すると言われています。
今回は国土交通DPFデータに連携されているGTFSのデータを活用し、公共交通空白地域を見ていきます。
GTFSって?
ChatGPTに聞いてみました。
GTFSは、公共交通機関の運行情報を共有するためのフォーマットです。これにより、アプリやウェブサイトでバスや電車の時刻表や経路を提供できます。公共交通機関の情報をコンピュータで利用しやすくすることで、効率的な移動やスケジュールの立て方ができるようになります。
だそうです。もっと知りたい!という方は以下をご確認ください。
GTFSデータの取得
今回もAPIを利用してデータを取得していきます。
最早お馴染みとなったデータを取得する関数を今回も使いまわします。
(データを取得する関数については16日目の記事をご覧ください)
送信するリクエストボディは次のような内容です。
データセットIDにGTFSレポジトリのIDを指定し、また今回は富山県のデータを指定しています。
graphql_query = """
query {
search(
term: "",
phraseMatch: true,
first: 0,
size: 3000,
attributeFilter: {
AND:[
{
attributeName: "DPF:dataset_id",
is: "gtfs"
},
{
attributeName: "DPF:prefecture_code",
is: 16
}
]
}
) {
totalNumber
searchResults {
title
lat
lon
shape
}
}
}
"""
これまでと同様にリクエストを送信し、結果をDataFrameに格納します。
data = send_request(query=graphql_query)
df: pd.DataFrame = pd.json_normalize(data["search"]["searchResults"])
df.head()
バス停データの抽出
バス停情報のMULTIPOINT
と路線情報のLINESTRING
がFeatureCollection
として1つのレコードに格納されており、バス停の座標のみを取り出すのがなかなか手ごわい。。。
今回は以下のようにバス停情報を抽出しました。効率的な方法があれば是非ご教示ください!
まずFeatureCollectionをGeoDataFrameに変換します。
import geopandas as gpd
from shapely.geometry import Point, MultiPoint
gdf_list = []
# 各行のFeatureCollectionからGeoDataFrameを作成し、リストに追加
for features in df["shape.features"]:
gdf_list.append(gpd.GeoDataFrame.from_features(features))
# リストのGeoDataFrameを連結
gdf = pd.concat(gdf_list, ignore_index=True)
gdf.head()
title
がstops
のレコードだけに絞り込み、路線のLINESTRINGを除きます。
gdf = gdf[gdf_concat["title"]=="stops"]
gdf.head()
各レコードのMULTIPOINT
を展開して座標を取り出します。
geometry = gdf["geometry"].explode(index_parts=False)
geometry.head()
geometry | |
---|---|
0 | POINT (136.878041 36.558079) |
0 | POINT (136.873596 36.559238) |
0 | POINT (136.874134 36.559268) |
0 | POINT (136.871949 36.560099) |
0 | POINT (136.872045 36.560236) |
GeoDataFrameに変換します。
bus_stops = gpd.GeoDataFrame(geometry=geometry.reset_index(drop=True), crs="EPSG:4326")
bus_stops.head()
geometry | |
---|---|
0 | POINT (136.878041 36.558079) |
1 | POINT (136.873596 36.559238) |
2 | POINT (136.874134 36.559268) |
3 | POINT (136.871949 36.560099) |
4 | POINT (136.872045 36.560236) |
ようやくバス停情報を取得することができました!
公共交通空白地域の確認
富山県内のバス停の座標を取得できたので、徒歩圏域としてバス停からの半径300mの円バッファを作成します。
GTFSの座標は緯度・経度の形式で度単位のためメートル単位の平面直角座標系に変換してからバッファを作成し、また度単位に戻しています。
bus_stop_buffer = bus_stops.to_crs(6675).buffer(300).to_crs(4326)
bus_stop_buffer.head()
Web地図上で確認します。
m = folium.Map(tiles="http://cyberjapandata.gsi.go.jp/xyz/pale/{z}/{x}/{y}.png", attr="地理院タイル")
folium.GeoJson(bus_stop_buffer, name="buffer").add_to(m)
m
可視化することができました!
空白地域が多く見えますが鉄道駅を追加するとまた違う結果になると思います。
まとめ
今回はGTFSのバスデータのみで単純な円バッファでの可視化となりましたが、国土交通DPFのデータを活用して公共交通空白地域の可視化に取り組みました。
道路ネットワークを考慮した等時間圏域(Isochrone Map)にしたり、65歳以上人口の地域メッシュデータと重ねてみたり、試したいことはまだまだあるのですが、時間が溶けていくので今回はここまでにします。。。
みなさまもぜひ国土交通DPFのデータを活用してみてください!
それではまた~