0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

首都圏の鉄道の運賃計算は複雑すぎた話

0
Last updated at Posted at 2026-02-10

久しぶりの記事投稿です。

「首都圏の最安運賃を簡単・高速・網羅的に調べることができるアプリ」公共交通オープンデータチャレンジ2025に応募していたのですが、落選したので供養の意味も込めて記事を書きました。

アプリとそのソースコードは公開しています。
今後も定期的に改善しようと思うので、コメントやIssue、プルリク歓迎です。

目次

作ったアプリについて

「1000円以内で到達できる駅と到達できない駅を可視化できないだろうか?」
「乗換案内アプリでも表示されないような最安経路は存在するだろうか?」

なんてことを思い、オープンデータを使って、首都圏の 最安運賃 を簡単・高速・網羅的に調べることができるアプリを作りました。

出発駅を指定することで、その駅から到達可能な全ての駅までの最安運賃をマップ上にマーカーで表示、そして、マップ上に表示された駅(マーカー)をクリックすることで、出発駅から選択した駅までの 最安経路 を分かりやすく表示してくれます。

最安運賃を算出するための処理はリアルタイムで行なっていますが、事前のデータ整理と適切なアルゴリズムの利用により、ほぼ遅延なく結果を表示することができます。

アプリのスクリーンショット

対応している鉄道事業者について

現在、首都圏の以下の20の鉄道事業者に対応しています。

  • 東日本旅客鉄道 ※1 ※2 ※3
  • 相模鉄道
  • 東武鉄道
  • 西武鉄道 ※2
  • 東急電鉄
  • 京急電鉄
  • 小田急電鉄
  • 京王電鉄
  • 京成電鉄 ※1 ※3
  • 北総鉄道
  • 東京メトロ
  • 東京都交通局
  • 横浜市交通局
  • 東京臨海高速鉄道
  • 首都圏新都市鉄道(つくばエクスプレス) ※2
  • ゆりかもめ
  • 多摩都市モノレール
  • 東葉高速鉄道
  • 埼玉高速鉄道
  • 横浜高速鉄道

※1 運賃計算が非常に複雑なため運賃が正確ではない可能性がありますが、引き続き改善に取り組む予定です。
※2 運賃は2026年3月14日の運賃改定以降のものが表示されます。
※3 東日本旅客鉄道と京成電鉄は一部の路線が非対応になります。

最安運賃経路の算出のしくみ

最安経路や最短経路、最速経路などの 最短経路問題 を求める場合は一般的にダイクストラ法やその派生(A*アルゴリズムなど)が利用されます。

このアプリでも同様にダイクストラ法を利用して最安運賃(経路)の算出を行っています。

例えば、新宿駅(東日本旅客鉄道)から池袋駅(東日本旅客鉄道)への最安運賃算出の流れは以下です。

  1. スタート(新宿駅(東日本旅客鉄道))以外のノードへの移動費を ∞円 に設定
  2. スタートに隣接しているノード(新宿駅(東京メトロ)池袋駅(東日本旅客鉄道))について、現在の移動費よりも安い金額で到達可能な場合、移動費を更新
  3. 2のノードから隣接するノードについても、現在の移動費よりも安い金額で到達可能な場合、移動費を更新
  4. 3のノードから隣接するノードについても3を繰り返し、全てのノードの移動費が最低になれば終了して、経路を復元

上記の流れで、新宿駅(東日本旅客鉄道)から池袋駅(東日本旅客鉄道)への最安運賃をダイクストラ法で求めると、山手線(東日本旅客鉄道)経由よりも丸ノ内線(東京メトロ)経由のほうが最安経路となります。(2026/3/14以降の運賃で計算)

実際のノード数(駅数)は1600程度あるため、計算時間を減らすために、予めダイクストラ法で利用しやすい形式のグラフを生成しています。

最安運賃(経路)算出の流れ

使用したデータについて

  • 公共交通オープンデータセンター
     相模鉄道、東武鉄道、西武鉄道、東急電鉄、京急電鉄、東京メトロ、東京都交通局、横浜市交通局、東京臨海高速鉄道、首都圏新都市鉄道、ゆりかもめ、多摩都市モノレールの12社について、「駅情報」「路線系統情報」「運賃情報」 の3つのデータを使用しています。小田急電鉄と東日本旅客鉄道については、「駅情報」「路線系統情報」 の2つのデータを使用しています。
     なお、東日本旅客鉄道、相模鉄道、東武鉄道、西武鉄道、東急電鉄、京急電鉄、小田急電鉄の7社のデータは「公共交通オープンデータチャレンジ2025」限定のデータです。

  • 乗り継ぎ割引情報
     首都圏の鉄道では、別の鉄道事業者に乗り継ぎを行う場合、割引運賃が設定されていることがありますが、それを考慮した運賃の算出に対応しています。
    ★参考:
    首都圏乗継割引設定全区間

首都圏の鉄道の運賃計算は複雑すぎた

タイトルの通り、首都圏の鉄道の運賃計算が複雑すぎたので対応に苦労したポイントを共有します。

実キロと営業キロが異なる区間が存在する点

「実キロ」とは、実際に乗車した距離のことです。
一方で、「営業キロ」とは、運賃計算上の距離のことです。

「使用したデータについて」で記載した通り、「運賃情報」 の配布がない事業者については、累計キロ情報(Wikipedia)とキロ別運賃表(公式情報)から運賃を算出しています。

基本的には、2駅間の最短乗車距離の小数点以下を切り上げて、キロ別運賃表に当てはめることで運賃を求めることができます。

ただし、東日本旅客鉄道の「鶴見駅」付近や京成電鉄の「東成田 - 空港第2ビル」区間は、実キロに対して異なる営業キロが適用されています。

例として、鶴見駅から羽沢横浜国大駅までの運賃を考えてみます。鶴見駅から羽沢横浜国大駅まで最短乗車距離で移動しようとすると、

  1. 鶴見駅→川崎駅(京浜東北線)
  2. 川崎駅→武蔵小杉駅(南武線)
  3. 武蔵小杉駅→羽沢横浜国大駅(相鉄直通線)

といった経路になります。距離はそれぞれ、

  1. 鶴見駅→川崎駅(3.5km)
  2. 川崎駅→武蔵小杉駅(7.5km)
  3. 武蔵小杉駅→羽沢横浜国大駅(16.6km)

です。合計して小数点以下を切り上げると28kmとなるので、東日本旅客鉄道の「キロ別普通旅客運賃表(幹線)」に当てはめると528円になりそうですが、これは誤りです。

実際は、相鉄直通線や湘南新宿ラインでは鶴見駅に停車しません(そもそもホームが存在しません)が、鶴見駅に相鉄直通線が停車すると仮定して、鶴見駅から羽沢横浜国大駅の距離である8.8km(切り上げて9km)を運賃計算に利用します。

したがって、運賃は209円となります。

(東日本旅客鉄道は「鶴見駅」付近だけだと思っていますが、他にもあれば教えてください。。。)

実キロと営業キロが異なる区間の例

特定区間運賃や加算運賃が存在する点

1つ上の内容と考え方は似ていますが、東日本旅客鉄道や京成電鉄には以下のような特定区間運賃や加算運賃の例を設定している区間が存在します。

  • 品川駅-横浜駅など、他社線と競合する区間(約30区間)は累計キロによらず特定運賃を設定(東日本旅客鉄道)
  • 東成田駅、成田空港駅、空港第2ビル駅発着の場合は70円もしくは140円を加算(京成電鉄)
  • 京成幕張本郷駅-京成千葉駅・千葉中央駅は累計キロによらず特定運賃を設定(京成電鉄)

東日本旅客鉄道の特定区間運賃については、こちらを参考にしてみてください。
京成電鉄については、こちらの方が詳しくまとめてくれています。

累計キロが打ち切りされるパターンが存在する点

運賃計算において、一般的には累計キロは通算され、キロ別運賃表も1つのみ用意されているパターンが大半です。

例えば、京王電鉄の京王線と井の頭線は同一のキロ別運賃表が利用され、累計キロも通算されます。

(例)渋谷駅(井の頭線)-京王八王子駅(京王線)の運賃

  1. 渋谷駅→明大前駅(井の頭線:4.9km)
  2. 明大前駅→京王八王子駅(京王線:32.7km)

 → 合計して小数点以下を切り上げると38kmとなり、運賃は409円となる。

しかし、京成電鉄では、本線、千葉線、金町線、押上線、東成田線のキロ別運賃表と、それ以外の路線(成田空港線や松戸線)のキロ別運賃表がそれぞれ存在しています。

京成電鉄の各種キロ別運賃表

(出典:京成電鉄の運賃制度 2025年4月版

例えば、押上駅から成田湯川駅まで最短乗車距離で移動しようとすると、

  1. 押上駅→青砥駅(押上線:5.7km)
  2. 青砥駅→京成高砂駅(本線:1.2km)
  3. 京成高砂駅→成田湯川駅(成田空港線:40.7km)

となりますが、押上線と本線は累計キロが合算されるので、運賃計算においては、

  1. 押上駅→京成高砂駅(押上線、本線:6.9km)
  2. 京成高砂駅→成田湯川駅(成田空港線:40.7km)

押上線、本線分が199円、成田空港線分が922円となり、運賃を合算すると1121円となります。

(ちなみに、成田空港線は北総電鉄のキロ別運賃の考慮が必要なパターンも存在するのでさらに複雑です。。。)

累計キロが打ち切りされるパターンの例

キロ別運賃表が複数存在するが、累計キロは合算されるパターンが存在する点

東日本旅客鉄道では、京成電鉄のように都市部(幹線)と地方部(地方交通線)で異なるキロ別運賃表が適用されます。

首都圏の路線は大半が幹線ですが、「八高線」(八王子と高崎を結ぶ路線)などは地方交通線のキロ別運賃表が適用されます。

運賃計算では、京成電鉄と同様に、「幹線に乗車した距離」と「地方交通線に乗車した距離」でそれぞれのキロ別運賃表から運賃を計算し、運賃を合算すれば良いのでは?
となりそうですが、これは誤りです。

東日本旅客鉄道では、以下のような方法で運賃の計算を実施します。

乗車した路線 運賃計算に用いるキロ 適用する運賃表
幹線のみ 営業キロ 幹線
幹線・地方交通線
(合計10km以上)
運賃計算キロ
(「地方交通線」の営業キロを1.1倍する。)
幹線
幹線・地方交通線
(合計10km未満)
営業キロ 地方交通線
地方交通線のみ 営業キロ 地方交通線

ややこしすぎて初見で理解できませんでした。。。。

幹線のみ、地方交通線のみの乗車の場合は特筆することも無いので、幹線と地方交通線を連続して乗車したパターンの運賃を例で説明します。

  • 「幹線・地方交通線(合計10km未満)」 の場合

例えば、高尾駅から北八王子駅まで最短乗車距離で移動しようとすると、

  1. 高尾駅→八王子駅(中央線快速:5.7km)
  2. 八王子駅→北八王子駅(八高線:3.1km)

となり、合計して小数点以下を切り上げると9kmとなるので、運賃は「キロ別普通旅客運賃表(地方交通線)」を参考に220円となります。

  • 「幹線・地方交通線(合計10km以上)」 の場合

ややこしいのはこちらです。
例えば、高尾駅から拝島駅まで最短乗車距離で移動しようとすると、

  1. 高尾駅→八王子駅(中央線快速:5.7km)
  2. 八王子駅→拝島駅(八高線:9.9km)

となり、合計は15.6kmとなります。
この場合、地方交通線である「八高線」の乗車距離を1.1倍します。

  1. 高尾駅→八王子駅(中央線快速:5.7km)
  2. 八王子駅→拝島駅(八高線:10.89km)

これを合計して小数点以下を切り上げると17kmとなるので、運賃は「キロ別普通旅客運賃表(幹線)」を参考に341円となります。



ここまでの説明を聞いて、
首都圏の鉄道の運賃を対象にしているのだから、「地方交通線」を除外すれば良いのではと思ったかもしれませんが、そういうわけにもいかない理由があります。

例えば、茅ヶ崎駅から高崎駅までの運賃を求めたいとします。

もし在来線で移動するなら、

  1. 茅ヶ崎駅→東京駅(東海道線:58.6km)
  2. 東京駅→高崎駅(高崎線:105.2km)

の合計163.8kmのルートを選択すると思います。いずれも幹線なので運賃は「キロ別普通旅客運賃表(幹線)」を参考に3190円となりますが、これは誤りです。

なぜなら、

  1. 茅ヶ崎駅→橋本駅(相模線:33.3km)
  2. 橋本駅→八王子駅(横浜線:8.8km)
  3. 八王子駅→高崎駅(八高線:96.4km)

のルートが存在し、合計は138.5kmとなり、地方交通線(八高線)の距離を1.1倍しても、

  1. 茅ヶ崎駅→橋本駅(相模線:33.3km)
  2. 橋本駅→八王子駅(横浜線:8.8km)
  3. 八王子駅→高崎駅(八高線:106.04km)

合計は148.14kmとなるからです。この距離を「キロ別普通旅客運賃表(幹線)」に当てはめると、運賃は2750円となります。

すなわち、幹線のみで移動できる区間であっても、地方交通線を通るルートを考慮する必要があるということです。

幹線と地方交通線を連続して乗車したパターンの例

都営地下鉄と東京メトロを乗り継ぐ場合に70円割引が適用される点

都営地下鉄に乗車した後、東京メトロに乗車した場合、またはその逆において、全体の運賃から70円割引になります。

ここまで読んで、割引なんて簡単だろと思うかもしれませんが、都営地下鉄と東京メトロの割引処理に非常に苦労しました。

最安運賃経路の算出のしくみで説明したように、最安運賃経路を求めるためにはダイクストラ法を利用しています。

例えば、浜松町駅(東日本旅客鉄道)から池袋駅(東日本旅客鉄道)への最安運賃算出は以下のようなグラフを使って、ダイクストラ法を適用すれば、最安経路を求めることができると考えていました。

負の閉路が存在するグラフ

しかし、上記のグラフでは、最安経路を求めることはできません。

なぜなら、ダイクストラ法は非常に便利なものですが、欠点が存在し、負の閉路 が存在するグラフには利用できないからです。

どの部分が負の閉路かというと、麻布十番駅(都営地下鉄)麻布十番駅(東京メトロ)間が双方向で行き来可能なため、負の閉路を形成してしまいます。

麻布十番駅(都営地下鉄)麻布十番駅(東京メトロ)を行き来すると無限に運賃が下がってしまうので、ダイクストラ法が利用できず、グラフの再設計を行うことになりました。

結論から言うと、東京メトロ全駅と都営地下鉄全駅の「全駅対全駅」の最安運賃(経路)をあらかじめ求めてグラフ化することで、負の閉路を排除しました。

イメージは以下のグラフで、このグラフであればダイクストラ法で最安運賃(経路)を求めることが可能になります。

負の閉路を排除したグラフ

乗継で双方が初乗り運賃となる場合に割引が適用される点

例えば、東急電鉄から東京メトロにとある駅で乗り換えを行う場合、東急電鉄側と東京メトロ側の 「双方が初乗り運賃」 となる場合に10〜20円程度の割引が適用されます。

1つ上と似ていますが、こちらは非常に数が多く、割引の適用に苦労しました。

見てもらった方が早いので、こちらをご覧ください。

全てで約2700もの組み合わせがありますが、自動化を駆使して何とか対応させました。。。

まとめ

いろいろ書いてみると結構長くなってしまいました。

本当はファイナルに進みたかったですが、記事としてまとめることができたので良しとします。

アプリのデプロイ後に可能な限り確認はしましたが、たぶん、まだバグや計算ミスなどが残っていると思うので、気軽にコメントやバグ報告を頂けると助かります。

0
0
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
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?