やんばる急行バスと学ぶ標準的なバス情報フォーマット(GTFS-JP) Ver.1

[ヴァル研究所 Advent Calendar 2018](https://qiita.com/advent-calendar/2018/val) 11日目です。

昨年3月に策定された日本における路線バスの路線図や時刻表、運賃表などをデータ化する際のフォーマット「標準的なバス情報フォーマット(GTFS-JP)」について、沖縄県の路線バス「やんばる急行バス」を例にとりながら説明する解説兼学習記録記事です。

<font color="Crimson">2019/03/27に動的情報のフォーマットも含んだ「標準的なバス情報フォーマット」のVer.2が発表されています。使いたいバージョンに気をつけてください。↓</font>
http://www.mlit.go.jp/sogoseisaku/transport/sosei_transport_tk_000067.html

# 標準的なバス情報フォーマットとは
「標準的なバス情報フォーマット」は国土交通省が昨年3月に取りまとめたフォーマットです。日本の路線バスに関するインターネット上の情報がより拡充されることを期待し、バス事業者と経路検索事業者とが時刻表や運賃をはじめとするデータの受渡しする際のフォーマットとして定められました。
国際的な公共交通情報フォーマットのデファクトスタンダードとなっている「GTFS」を互換性を保ちながら拡張したフォーマットであるため、最近では「GTFS-JP」とも呼ばれています(本記事でも以下GTFS-JPと表します。)。

## そもそもGTFSって?
GTFSは「General Transit Feed Specification」の略で、公共交通機関の時刻表と地理的情報に関するフォーマットとしてデファクトスタンダートになりつつあります。元となった「Google Transit Feed Specification」は2005年にGoogleがオレゴンの交通事業者TriMetとともに策定しました。その後、フォーマットが広く公開されるとともに、より広範に利用されるよう先述の「General~」に改称されました。
GTFSは以下の特徴を持っています。

* CSV形式で記述された複数のテキストファイルをまとめたZIPファイルである。
* テキストエディタや表計算ソフトしか利用できない交通事業者でも活用できるよう、簡便な仕様になっている。
* 必須項目が少なく、任意項目が多いため、スモールスタートが可能。

GTFSの策定に関する話題は、GTFS-JPの策定にも携わった @niyalist さんのこちらの記事が詳しいです。(読むたびに身が引き締まります。)
[オープンデータ標準を作る： GTFS物語](https://qiita.com/niyalist/items/5eef5f9fef7fa1dc6644)

## GTFS-JPについて
先述の通り、GTFS-JPは本家GTFSを互換を保ちながら拡張したフォーマットです。GTFSが持つ特徴もそのまま引き継いでいますが、GTFSと比べ以下の特徴があります。

* 日本の事情に合わせ、拡張された項目が存在する。
    * 複雑な系統を表すため、経路関係の情報が拡張
    * 運賃計算へのニーズが高いため、運賃関係の情報入力が強く推奨
* 経路検索事業者への情報提供を意図し拡張された項目が存在する。
    * 時刻表などの有効期限の情報入力が強く推奨

そのほかの特徴は、各項目に触れながら解説します。

GTFS-JPはすでに交通事業者から経路検索事業者への情報提供に利用されています。GoogleMapsやヴァル研究所の「駅すぱあと」もその一つです。また最近では経路検索事業者への情報提供にとどまらない利用を期待し、GTFS-JPに乗っ取って作成されたデータを、オープンデータとして公開する流れも広がっています。[この](http://tshimada291.sakura.ne.jp/transport/gtfs-list.html?fbclid=IwAR2mOpu7ts9EsiOD7GluuozcrDgTpt2Tgh5WLnCFSMlzcf4iivLtE8w7dYk)ページでその一覧を見ることができます。

すでにオープンなっているデータを実際に使ってみた記事も書いています。ぜひご覧ください。
[オープンソースの経路探索「OpenTripPlanner」をUbuntuで動かして岡山県で経路探索をする](https://qiita.com/kumatira/items/658e7b75785c854f0f69)

また本記事で題材とする「やんばる急行バス」のGTFS-JPデータもこちらで公開されているものを利用しています。
[やんばる急行バス公式HP GTFSデータ](http://yanbaru-expressbus.com/gtfs%E3%83%87%E3%83%BC%E3%82%BF/)

# 触ってみる
では実際に「やんばる急行バス」から公開されているGTFS-JPのデータを触ってみましょう。実際のデータは先述の[このページ](http://yanbaru-expressbus.com/gtfs%E3%83%87%E3%83%BC%E3%82%BF/)より落としてきます。GTFSデータと紹介されていますが、中身はGTFS-JPのデータです。

**「やんばる急行バス」について**
やんばる急行バスは沖縄本島南部の那覇空港から北部の運天港までを走っている路線バスです。路線が単純な往復の1路線しかなく、一日の便数も9往復程度であることから、学習の題材として選びました。

## 構成
ダウンロードしてきたZIPを解凍すると以下のように、テキストファイルが13個入っていると思います。

* agency.txt
* fare_rules.txt
* stops.txt
* agency_jp.txt
* feed_info.txt
* translations.txt
* calendar.txt
* routes.txt
* trips.txt
* calendar_dates.txt
* shapes.txt
* fare_attributes.txt
* stop_times.txt

それぞれがCSV形式になっていて、互いにリレーションを持っています。DBの複数のテーブルをダンプしたでっかいCSVと理解するとわかりやすいかもしれません。

それぞれのファイルを、いくつかの項目に分けて、見ていきます。
また説明は、国土交通省より出されている[「標準的なバス情報フォーマット」解説](http://www.mlit.go.jp/common/001179007.pdf)に沿って行います。

## 各ファイルについて
### agency.txt と agency_jp.txt
解説書では9ページで言及されています。
この2つのファイルでは、交通事業者に関する基礎的な情報が設定されています。agency.txtに書かれている項目は、経路検索サービス上で交通事業者への問い合わせ誘導などで利用されます。

また経路検索サービスだけでなく、電子申請用ソフトなどでの利用も意図されているGTFS-JPでは、任意項目として「agency_jp.txt」　が追加されています。ここには会社住所や代表者名など役所への申請で使うような項目が並んでいます。

**agency.txt**

| 項目名|例||
|:-----------------|:------------------|:------------------|
|agency_id|1360003007856|事業者IDであり、他のテーブルでも利用されるキー。GTFS-JPでは事業者の法人番号を用いる。|
|agency_name|やんばる急行バス|経路検索サービスで表示されたい名称。正式名称である必要はなく、愛称を設定している事業者も多い。|
|agency_url|http://yanbaru-expressbus.com/|公式HPのアドレス。利用者が事業者へ問い合わせをしたい場合、経路検索サービスではここのアドレスを表示する(こともある)|
|agency_timezone|Asia/Tokyo|タイムゾーン。「Asia/Tokyo」に固定|
|agency_lang|ja|言語。同じく固定|
|agency_phone|0980-56-5760|agency_urlと同様|
|agency_fare_url|(空白)|予約ができるURLを設定する|

**agency_jp.txt**

| 項目名|例||
|:-----------------|:------------------|:------------------|
|agency_id|1360003007856|agency.txtで定義されている|
(以下略)


### stops.txt
解説書では11ページで言及されています。
標柱と停留所という概念があります。標柱はバス停にあるポール1本を指し、停留所はそれを束ねたものです。

例えばこのようなバス停が有ったとします。このとき青丸が標柱、赤い囲いが停留所を表します。

<img width="612" alt="スクリーンショット 2018-12-25 15.40.56.png" src="https://qiita-image-store.s3.amazonaws.com/0/159912/88d55e0c-9b40-77f9-c14d-51b27b8f1edf.png">

標柱を停留所にまとめることで、経路検索サービスなどで一つのまとまった停留所として案内することができます。解説書では標柱を停留所として束ねることを必須ではないが推奨としています。

複雑な運行形態を持たない「やんばる急行バス」では全てを標柱として表現し、それらをまとめた停留所は設定していません。逆に3つ以上の標柱が同じ名称であるバスターミナルや、複数の系統が同じ停留所として異なる標柱を使うパターンをもつ事業者は、標柱をまとめた停留所を設定しているようです。

| 項目名|例||
|:-----------------|:------------------|:------------------|
|stop_id|100_01|標柱や停留所を示すIDで、他のテーブルでも利用されるキー。|
|stop_code|(空白)|旅客向けの記号や番号を入れる。標柱がいくつもあるようなバスターミナルだと使う。あくまで案内用|
|stop_name|那覇空港国内線|標柱や停留所の名前|
|stop_desc|(空白)|付加情報がつけられる。|
|stop_lat|26.206788|標柱の緯度|
|stop_lon|127.651162|標柱の経度|
|zone_id|100_01|運賃エリアを定義するIDで、他のテーブルでも利用されるキー。標柱のみに設定できる。fare_rules.txtで「このzone_idからこのzone_idまではこのルール」という風に利用できる。そのため、ゾーン制運賃のときはそのゾーンのID。キロ制運賃のときはstop_idをそのまま入れる。|
|stop_url|(空白)|標柱や停留所についてのURLがある場合は入れる|
|location_type|0|標柱は0、停留所は1を入れる。やんばる急行バスの場合、停留所は存在しないので全行0が入っている。|

### routes.txt
解説書では13ページに言及されています。
このファイルではバスが運行される「経路」を設定します。

経路は同じ標柱に同じ順番かつ同じ運賃で走る運行便をまとめたものです。よって以下は全て異なる経路として管理します。

* 逆向きの便(上り/下り)
* 途中の経由が異なる便
* 途中に通過がある便(急行など)
* 運賃形態が違う便(深夜路線など)

GTFS-JPでは任意の情報として「route_jp.txt」を設定することもできます。これはroutes.txtで設定された経路とroute_idを通じてひも付いており、それぞれの経路を束ねた「系統」や「路線」を設定することができます。経路検索サービスの案内などで活用できそうです。
なお「やんばる急行バス」は複雑な経路を持っていないため、それらを束ねた「系統」や「路線」も設定されておらず、route_jp.txtも存在しません。

| 項目名|例||
|:-----------------|:------------------|:------------------|
|route_id|112001|経路を示すIDで、他のテーブルでも利用されるキー。|
|agency_id|1360003007856|agency.txtで設定されているagency_id|
|route_short_name|(空白)|系統番号(例:東01)や路線名称(例:〇〇線)などこの経路を識別することのできる略称があれば記載する。route_long_nameで事足りる場合は空白でも良い。|
|route_long_name|やんばる急行バス(那覇空港－運天港)|詳細な情報を含んだ経路の名称を設定する。route_short_nameで事足りる場合は空白でも良い|
|route_desc|(空白)|経路に関する説明があれば記載。「学休日は運休」などと記載していれば経路検索サービスなどで案内することができる。ただし運行日の案内はcalendar.txtで行うのが良い。便単位で案内する場合はtrips.txtでも設定できる。|
|route_type|3|バスは3に固定。[ここ](https://sites.google.com/site/gtfschanges/proposals/route-type)で他の交通種別の場合の値が見られる。やんばる急行バスはバスなので全経路が3|

### trips.txt
解説書では15ページに言及されています。
運行される便に関する情報を設定します。便について解説書では「旅客が連続して乗車可能な1回の運行を1つの便」とするとしています。要は起点から終点までを持つ１回の運行を指します。そのため、運行する便数がそのまま行数になります。


| 項目名|例||
|:-----------------|:------------------|:------------------|
|route_id|111002|routes.txtで設定されているroute_id。その便が運行する経路を設定する。|
|service_id|通年|後述のcalendar.txtで設定されているservice_id。運航日のパターンを設定する。やんばる急行バスは通年でダイヤが変わらないため、「通年」というIDが設定されている。このIDの指す内容はcalendar.txtで定義されている。|
|trip_id|通年_05時00分_系統111002|便を示すIDで、他のテーブルでも利用されるキー。やんばる急行バスでは、service_idと出発時刻、route_idを用いることで一意に定まるIDを生成している。|
|trip_headsign|(空白)|便の行き先や経由を表す文字列を設定する。バスの先頭に掲げられているヘッドサインのイメージが近い。|
|shape_id|111111|後述のshapes.txtで設定されているshape_id。この便が通る経路の描画情報が指定されている。|

### stop_times.txt
解説書では17ページに言及されています。
ある便がある標柱をいつ到着しいつ出発するのかを設定することができます。そのため、運行する全ての便のそれぞれの停車標柱数を全て合計した数が、ファイルの行数と一致します。

| 項目名|例||
|:-----------------|:------------------|:------------------|
|trip_id|通年_05時00分_系統111002|trips.txtで設定されているtrip_id。この行がどの便についての設定なのかを決めている。|
|arrival_time|05:00:00|その標柱への到着時刻。HH:MM:SS形式で設定する。|
|departure_time|05:00:00|その標柱からの出発時刻。HH:MM:SS形式で設定する。|
|stop_id|350_02|stops.txt.で設定されているstop_id。この行がどの標柱についての設定なのかを決めている。|
|stop_sequence|1|その便でのその標柱の通過の順番を設定する。昇順であればよく連番である必要はない。|
|stop_headsign|那覇空港国際線|その標柱を通過する時点でバスの先頭のヘッドサインに示されている文字列を設定する。この値が設定されている場合、trips.txtのtrip_headsignは上書かれる。循環系統や経由地がある系統の場合、標柱の通過段階によってそのヘッドサインの内容は異なる(例えば「〇〇経由」の〇〇をすぎたあとは「〇〇経由」を出さないなど)。やんばる急行バスの場合、始発標柱の時点で最後まで表示するヘッドサインを出しているため、便の途中でstop_headsignは変わらない。またここでstop_headsignを設定しているため、trips.txtのtrip_headsignは空白になっている。|
|pickup_type|0|乗車に関する区分を設定します。0では通常の乗車地であることを、1では乗車不可能であることを示す。|
|drop_off_type|1|降車に関する区分を設定します。0では通常の降車地であることを、1では降車不可能であることを示す。|

**始発標柱の場合**
始発標柱ではarrival_timeにdeparture_timeと同じ時刻を指定します。また始発標柱で降りることはできないためdrop_off_typeは1を指定します。

**最終標柱の場合**
最終標柱ではdeparture_timeにarrival_timeと同じ時刻を指定します。また最終標柱で乗ることはできないためpickup_typeは1を指定します。

### calendar.txtとcalendar_dates.txt
解説書では19ページで言及されています。
この二つのファイルによって運行日カレンダーを作ることができます。calendar.txtではservice_idで定められる運行のパターンを曜日に基づいて作成することができます。「平日(月火水木金を１、土日を0)」や「通年(全曜日を1)」のようなパターンです。
またcalendar_dates.txtでは上記の曜日のパターンに依らない日の設定を行うことができます。解説書では祝日や学休日が例として挙げられています。

この二つを組み合わせることで、月曜日は「平日」とする、ただし1月14日は「平日」ではなく「休日」とする、などの設定ができます。

**calendar.txt**

| 項目名|例||
|:-----------------|:------------------|:------------------|
|service_id|通年|運行パターンを示すIDで、他のテーブルでも利用されるキー。|
|monday|1|月曜日についてこの運行パターンが該当するか示す。1なら運行。0なら非運行|
|(略)|||
|sunday|1|日曜日についてこの運行パターンが該当するか示す。1なら運行。0なら非運行|
|start_date|20180322|この運行パターンが開始される日をYYYYMMDD形式で設定する。この値によりダイヤ改正前後のパターンを分けることができる|
|end_date|20190421|この運行パターンが終了する日をYYYYMMDD形式で設定する。|

**calendar_dates.txt**

| 項目名|例||
|:-----------------|:------------------|:------------------|
|service_id|(空白)|alendar.txtで設定されているservice_id。この行がどの運行パターンについて設定しているかを定める。|
|date|(空白)|この行がどの日について設定しているかを定める。|
|exception_type|(空白)|dateに定めた日に、service_idをどう適用するかを定める。1なら適用する。2なら適用しない|

先述の例のように、通常「平日」として運行されるが、ある特定の日のみ「休日」として運行される場合、その日について「平日」を非適用にする行、その日について「休日」を適用とする行の合わせて2行で設定します。

(例)

|service_id|date|exception_type||
|:-----------------|:------------------|:------------------|:------------------|
|平日|20190117|2|2019年1月17日について「平日」を非適用にする|
|休日|20190117|1|2019年1月17日について「休日」を適用する|

やんばる急行バスの場合、祝日も関係なく「通年」のダイヤで運行するため、calendar_dates.txtは1行も存在していません。

### fare_attributes.txtとfare_rules.txt
解説書では21ページで言及されています。
この2つのファイルによって運賃に関する情報を設定します。GTFSでは任意とされていますが、日本では経路検索サービスにおける運賃情報へのニーズが高いことからGTFS-JPでは推奨とされています。

fare_attributes.txtでは運賃のパターンやその属性(金額や支払いタイミングなど)を設定し、fare_rules.txtではその運賃パターンをどの区間において適用するかを設定します。

**fare_attributes.txt**

| 項目名|例||
|:-----------------|:------------------|:------------------|
|fare_id|Fare160yen_00|運賃パターンをを示すIDで、他のテーブルでも利用されるキー。やんばる急行バスの場合は運賃+通し番号で生成されている。|
|price|160|運賃|
|currency_type|JPY|通貨。GTFS-JPでは「JPY」に固定されている。|
|payment_method|0|支払いのタイミングを設定する。0で後払い、1で前払い|
|transfers|0|この運賃パターンについて支払ったあと、何回まで乗り換えても運賃が有効であるかを示す。|

**fare_rules.txt**

| 項目名|例||
|:-----------------|:------------------|:------------------|
|fare_id|Fare220yen_00|fare_attributes.txtで設定されているfare_id。|
|route_id|112001|toutes.txtで設定されているroute_id。どの経路について設定するかを定める。|
|origin_id|100_01|stops.txtで設定されているzone_id。この運賃パターンが適用される最初のzone_idを設定する。|
|destination_id|110_01|stops.txtで設定されているzone_id。この運賃パターンが適用される最後のzone_idを設定する。|

やんばる急行バスはソーン制ではなくキロ制運賃を敷いています。そのため、stops.txtで設定されているように全ての標柱のzone_idが異なります。よってfare_rules.txtでも各経路の各標柱間について設定されています。

###  shapes.txt
解説書では22ページに言及されています。
shapes.txtでは標柱以外の経路上において、どこを通るのかを位置情報を羅列することで設定しています。設定がなくても経路検索サービスでは問題ないですが、shapes.txtを参照するアプリケーションでは地図上に正確に経路を表現することができます。

**shapes.txt**

| 項目名|例||
|:-----------------|:------------------|:------------------|
|shape_id|111111|点のまとまりである線を示すIDで、他のテーブルでも利用されるキー。|
|shape_pt_lat|26.67794635|点の緯度|
|shape_pt_lon|127.9968017|点の経度|
|shape_pt_sequence|0|点のまとまりである線の中で、この点が何番目であるかを設定する。|

GoogleMapsを始めとるする経路検索サービスでは、ある標柱とshapeを結びつける際、その標柱の位置情報にもっとも近い点(shape_pt_lat/shape_pt_lng)を利用します。そのため、標柱に近い点がなかったり、標柱の順番と点の順番が異なっている場合はエラーになります。

詳しくは[Google公式のガイダンス](https://support.google.com/transitpartners/answer/2753308?hl=ja)などを参照してください。

### translations.txt
解説書では24ページで言及されています。
translations.txtでは標柱名(stops.txtのstop_name)などの翻訳対照を設定することができます。この翻訳には日本語のふりがなも含まれています。解説書では翻訳の対応は優先度や業務負荷と相談した上で実施するべきとしています。やんばる急行バスは観光地路線でありインバウンド需要が高いためか、

* 日本語ふりがな
* 英語
* 中国語(簡体)
* 中国語(繁体)
* 韓国語

での翻訳が対応されています。

**translations.txt**

| 項目名|例||
|:-----------------|:------------------|:------------------|
|trans_id|那覇空港国内線|元となる単語|
|lang|zh-CN|翻訳先の言語を設定する。ISO639-1コードに基づいて指定する。|
|translation|那霸机场国内线航站楼|翻訳した単語|

trans_idに指定されている単語が、対象となる項目(末尾が`_name`,`_desc`,`_headsign`,`_url`の項目)に含まれる場合、問答無用で翻訳されます。そのため、翻訳元となる単語が重なる場合などは括弧書きをつけ、翻訳をそれぞれ振り分けるなどする必要があります。

### feed_info.txt
解説書では23ページに言及されています。
GTFS-JPに基づき公開されたデータに付随する情報を設定します。GTFSでは必須とされていませんが、GTFS-JPでは必須とされています。これは提供を受ける経路検索事業者が、そのデータの「鮮度」に関するニーズを持っているためです。
解説書では、有効期限を1年程度と定め、ダイヤ改正がなくとも1年に1回程度、データを作り直し公開、提供するのが望ましいとしています。

| 項目名|例||
|:-----------------|:------------------|:------------------|
|feed_publisher_name|やんばる急行バス|データを公開する事業者の正式名称を指定する|
|feed_publisher_url|http://yanbaru-expressbus.com/|データを公開する事業者のURLを指定する。|
|feed_lang|ja|データの提供される言語を指定する。GTFS-JPでは「ja」で固定される。|
|feed_start_date|20180421|YYYYMMDD形式でこのデータの有効期間の始まりを設定する。|
|feed_end_date|20190420|YYYYMMDD形式でこのデータの有効期間の終わりを設定する。|
|feed_version|20180322_2018年03月22日（やんばる急行バス-停留所移設）|このデータを一意に定めるバージョン名を設定する。やんばる急行バスでは直近のダイヤ改正日時とその理由を用いて生成している|

# まとめ
以上、13個の項目について解説しました。全体として、仕様が簡便かつ任意項目が多く、スモールスタートができる点が特徴と感じました。

解説書の写経になっている部分もありますが、ぜひやんばる急行バスのGTFS-JPデータを片手に読んでいただけると幸いです。
[やんばる急行バス公式HP GTFSデータ](http://yanbaru-expressbus.com/gtfs%E3%83%87%E3%83%BC%E3%82%BF/)


また解説書によるとGTFS-JPはさらなるアップデートが想定されているようです。そのあたりの知見も含め、随時追記していきたいと思います。また私自身はGTFS-JPデータを作成したことはないため、間違っている点等あればコメント、編集リクエストをいただけると嬉しいです。