LoginSignup
1
2

本記事は国土交通データプラットフォームアドベントカレンダー18日目の記事です。

はじめに

みなさん こんにちは

最近、ニュースでバスの運転手不足の問題についてよく見ます。

バス路線が廃止されると公共交通空白地域が広がり、交通難民が増加すると言われています。
今回は国土交通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()

gtfs_df (1).png

バス停データの抽出

バス停情報のMULTIPOINTと路線情報のLINESTRINGFeatureCollectionとして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()

gdf_1 (1).png

titlestopsのレコードだけに絞り込み、路線のLINESTRINGを除きます。

gdf = gdf[gdf_concat["title"]=="stops"]
gdf.head()

gdf_2 (1).png

各レコードの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()

buffer (1).png

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

map (1).png

可視化することができました!
空白地域が多く見えますが鉄道駅を追加するとまた違う結果になると思います。

まとめ

今回はGTFSのバスデータのみで単純な円バッファでの可視化となりましたが、国土交通DPFのデータを活用して公共交通空白地域の可視化に取り組みました。
道路ネットワークを考慮した等時間圏域(Isochrone Map)にしたり、65歳以上人口の地域メッシュデータと重ねてみたり、試したいことはまだまだあるのですが、時間が溶けていくので今回はここまでにします。。。

みなさまもぜひ国土交通DPFのデータを活用してみてください!
それではまた~

1
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
2