GTFS+ は標準以外の運賃(fare)をどう表現しているのか

# GTFS+ について
**GTFS+** はアメリカ、ベイエリア(サンフランシスコ湾周辺)の公共交通機関を管轄するMTC(Metropolitain Transportation Commission)が定めたGTFSの拡張フォーマットです。

仕様書はこちら → https://www.transitwiki.org/TransitWiki/images/e/e7/GTFS%2B_Additional_Files_Format_Ver_1.7.pdf

GTFS+はファイルやカラムを追加することで、GTFSと比べて以下のような情報を保持しています。

* 標準以外の運賃(小人運賃や年金生活者向け運賃、軍人向け運賃など)
* 駅や路線の追加情報(駅の所属する自治体など)
* 運行日の追加情報(運行パターンの名称など 例:`Sunday/Holiday`)

MTC配下にあるベイエリア周辺の交通事業者はGTFS+に基づいたオープンデータとして公開しています。例えば以下のような例があります。ただし全ての交通事業者が、GTFS+に完全に準拠したデータを提供している訳ではない点に留意して下さい。

* Caltrain [配布サイト](http://www.caltrain.com/developer.html)
* Petaluma Transit[配布サイト](https://transitfeeds.com/p/petaluma-transit-gtfs/675)
* Golden Gate Transit [配布サイト](https://transitfeeds.com/p/golden-gate-bridge-highway-transportation-district/349)

本記事ではサンフランシスコ都心とサンノゼ/ギルロイを結ぶ鉄道「Caltrain」のオープンデータを例に、GTFS+では標準以外の運賃がどう表現されているのかを解説します。

# GTFS+における標準以外の運賃の表現
ここでいう「標準」の運賃とはGTFSにおいて`fare_attributes.txt`と`fare_rules.txt`にて表現されている運賃、具体的には`fare_attributes.txt`の`price`の値を指します。GTFSでは運賃を表す値を1つしか保持できないため、ここには日本でいういわゆる「大人運賃」のような標準的な運賃のみが入っています。

しかし皆さんもご存知の通り、多くの公共交通機関には小人運賃や身障者運賃といった割引制度があり、同一区間を乗った場合でも標準的な運賃とは異なる運賃となることがあります。アメリカでは軍に関係する人向けの「military fare」があるほか、日本でもいわゆる「ICカード運賃」といった二重の運賃制度が敷かれていたりします。

GTFS+ではこういった運賃を`rider_categories.txt`と`fare_rider_categories.txt`を使って表現しています。

## rider_categories.txt
`rider_categories.txt`では後に紹介する`fare_rider_categories.txt`で使う、運賃の区分を定義します。カラムは以下の通りです。

| フィールド名 | 必須か | 説明 |
|-----------------------------|:------:|-----------|
| rider_category_id | ○ | rider_categoryのユニークなid(int)を付与します。<br> ただし以下の通り、事前に決まったカテゴリーに基づいて付与する必要があります。<br>2 - Senior(高齢者)<br>3 - Child(小人)<br>4 - Student(学生)<br>5 – Youth(若者)<br>6 - Disabled(障害者)<br>7 – Promotional category(セールとしての割引?)<br>11 – Military(軍関係者)<br>15 to 25 – Custom categories (独自に設定できる) |
| rider_category_desc ription | ○ | このカテゴリーを説明する文章です。 <br>例:Child (ages 5-11) |

## fare_rider_categories.txt
`rider_categories.txt`にて定義された`rider_category_id`を、`fare_attributes.txt`にて定義された`fare_id`に紐付け、その運賃も保持します。
(`fare_attributes.txt`の`fare_id`はどの区間の運賃か、という情報を持っています。)

| フィールド名 | 必須か | 説明 |
|-------------------|:------:|------------------------|
| fare_id | ○ | fare_attributes.txtにて定義されたfare_id この行がどの区間についての運賃を保持しているかを表します。 |
| rider_category_id | ○ |  rider_categories.txtにて定義されたrider_category_id  この行がどの区分の運賃を保持しているかを表します。 |
| price | ○ | 運賃を表します。GTFS+では単位はUS$です。 |

# Caltrainの例
実例としてCaltrainの配布するデータを見てみましょう。[配布サイト](http://www.caltrain.com/developer.html)からダウンロードしてきます。

![IMG_20180304_182744.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/159912/e426ea47-5b7f-cc6a-fc01-1640316a7f61.jpeg)
サンフランシスコ周辺の通勤需要を担うカルトレイン(筆者撮影)

## rider_categories.txt

| rider_category_id | rider_category_description |
|-------------------|----------------------------|
| 2 | Senior |
| 5 | Youth |
| 6 | Disabled |
| 15 | Medicare Cardholder |

2から6にはGTFS+に従ってそれぞれの運賃の区分が定義されています。その交通事業者に運賃区分が存在しない場合はGTFS+の定める全ての運賃区分を書き込む必要は無いようです。
また独自の設定が認められている15には`Medicare Cardholder`という説明のついた運賃区分が定められています。
>Medicare cardholder: customers who have a Medicare card.

[公式サイト](http://www.caltrain.com/Fares/tickettypes.html)にはこのようにしか書かれていませんが、社会保険で暮らす乗客向けといったところでしょうか?

## fare_rider_categories.txt

| fare_id | rider_category_id | price |
|---------|-------------------|-------|
| 3527 | 2 | 3.75 |
| 3527 | 5 | 3.75 |
| 3527 | 6 | 3.75 |
| 3527 | 15 | 3.75 |
| 3528 | 2 | 4.75 |
| 3528 | 5 | 4.75 |
| 3528 | 6 | 4.75 |
| 3528 | 15 | 4.75 |
|  | : |  |

`fare_id`に対して、それぞれの運賃区分で金額が書き込まれています。

この表だけでは、使い方が分からないので実例をあげます。ここではGoogleやAppleの本社がほど近い、Mountain View駅からサンフランシスコの都心にあるSan Francisco駅までの子供運賃を求めます。

まず当該区間の`fare_id`を知るため`stops.txt`と`fare_rules.txt`を参照します。

**stops.txt**

| stop_id | stop_name | stop_lat | stop_lon | zone_id |
|---------|------------------------|-----------|-------------|---------|
| 70011 | San Francisco Caltrain | 37.77639 | -122.394992 | 2275 |
| 70211 | Mountain View Caltrain | 37.394459 | -122.075956 | 2277 |
| : | : | : | : | : |

ここで定義されている通りMountain View駅の`zone_id`は`2277`、San Francisco駅の`sone_id`は`2275`です。

**fare_rules.txt**

| fare_id | route_id | origin_id | destination_id |
|---------|----------|-----------|----------------|
| 3527 | 12869 | 2277 | 2275 |
| 3527 | 12871 | 2272 | 2274 |
| 3527 | 12871 | 2272 | 2276 |
| : | : | : | : |

`zone_id` `2277`から`zone_id` `2275`の区間の運賃には`3527`という`fare_id`が振られています。

ここで先ほどの`fare_rider_categories.txt`のうち、`fare_id`が`3527`、`rider_category_id`が`5` (Youth)の行を見ると、運賃は3.75ドルであることがわかります。

ちなみに`fare_id`→`3527`を`fare_attributes.txt`で参照すると当該区間の標準の運賃は8.25ドルと定義されています。子供は半額以下なんですね。実際に公式サイトの[ゾーン区分](http://www.caltrain.com/stations/systemmap.html)および[運賃表](http://www.caltrain.com/Fares/farechart.html)を見るとこの運賃になっていることがわかります。

# まとめ
サンフランシスコ周辺のベイエリアの交通事業者のオープンデータで用いられているGTFS+において、標準以外の運賃がどのように表現されているかを解説しました。GoogleMapsが複数の運賃体系を表示しないということもあってか、本格的な普及までは至ってい無いようです。ただしアメリカは日本以上に運賃の区分が分かれている場合もあり、需要はあるのでは無いかと感じました。また地域の交通事業者がまとまってGTFSの拡張フォーマットを定めたという点も興味深いです。これは日本におけるGTFS-JPの流れにも似ていると感じました。

さらに今回解説した2つの拡張ファイルは、日本のICカード運賃の表現などにも応用できるかもしれません。
ただし記事内記載の通り、`fare_rider_categories.txt`の`price`にはUS$の値が入りますので、ここにも`currency_type`カラムを増やすなどいくつかの工夫は必要そうです。

# 国内のサンプル

[@aruneko99](https://twitter.com/aruneko99) さんのGitHubリポジトリにて、`rider_categories.txt`と`fare_rider_categories.txt`を追加した[道南バス](http://www.donanbus.co.jp/)のGTFSファイルが公開されています。サンプルとしてぜひご覧ください。
→ [aruneko/DonanbusGTFS](https://github.com/aruneko/DonanbusGTFS/releases)