路線バスの会社が乗降の記録(ICカード)から Python で系統・時間帯ごとの乗客数を予測し、ダイヤの見直しの候補を出す
ICカードの乗降の記録から、系統・方向・時間帯ごとの翌月以降の乗客数と最も混む区間の人数を幅つきで見込みます。定員と運行回数に照らし、増便・減便・時刻の移動を検討する便の候補を計画の担当に出します。
- 連携・自動化
- Python
- 対象業界
- その他/物流/自治体
- 対象部門
- 経営企画
- 対象業務
- 比較検討/集計・分析
- 主な課題
- データ分析に時間がかかる/判断に時間がかかる/属人化している
- AIで行う処理
- 予測
- 主な効果
- 判断支援/属人化解消/工数削減
- 導入難易度
- ★★★★☆
- 実装レベル
- 本格構成
- 費用感
- 個別開発(大)
- 人間の確認
- 条件付き
01導入前 / 導入後の業務フロー
- 精算の仕組みから前月の乗降の記録を書き出し、表計算で系統・方向・便ごとの乗車の人数を数える
- 降車の記録と突き合わせ、停留所の順に車内の人数を積み上げて、便ごとに最も混む区間を探す
- 現金の乗客の分を、系統ごとの決まった割合で上乗せする
- 前年の同じ月、前月と並べ、増えた便・減った便に印を付ける
- 学校の休み、祭り、病院の休診日などの事情を思い出し、来月以降どうなりそうかを書き込む
- 定員に近い便と、乗客の少ない便を拾い出し、見直しの候補の表を作る
- 課長が候補を見て、運行の部門と運転士の勤務の担当に相談する便を決める
- 自動毎月2日の朝、精算の仕組みから書き出された前月の乗降の記録と、運行の時刻のデータをプログラムが読み込む
- 自動乗車と降車を便ごとに組み合わせ、停留所の順に車内の人数を積み上げて、便ごとの乗車の人数と最も混む区間の人数を出す
- 自動系統・方向・時間帯・日の種類ごとに、翌月から3か月先までの乗客数と最も混む区間の人数を、真ん中と幅で見込む
- 自動定員と運行回数に照らし、混雑の候補・閑散の候補・前年からの変化が大きい系統に印を付け、検討表を更新する
- 人計画の担当が、印の付いた系統の根拠(時間帯ごとの人数、前年との差、効いた項目)を確かめ、事情を書き添える
- 人課長が、運行の部門と運転士の勤務の担当に相談する便を決める
- 人ダイヤの改正の案を作り、自治体との協議と運行計画の届出を進める(これまでどおり)
各工程の詳しい説明を読む
- 精算の仕組みから前月の乗降の記録を書き出し、表計算で系統・方向・便ごとの乗車の人数を数える
- 降車の記録と突き合わせ、停留所の順に車内の人数を積み上げて、便ごとに最も混む区間を探す
- 現金の乗客の分を、系統ごとの決まった割合で上乗せする
- 前年の同じ月、前月と並べ、増えた便・減った便に印を付ける
- 学校の休み、祭り、病院の休診日などの事情を思い出し、来月以降どうなりそうかを書き込む
- 定員に近い便と、乗客の少ない便を拾い出し、見直しの候補の表を作る
- 課長が候補を見て、運行の部門と運転士の勤務の担当に相談する便を決める
(a)2番目に時間がかかる。 便ごとに乗車と降車を停留所の順に並べ、車内の人数を積み上げる作業は、表計算の式を系統ごとに作り直しながら進めます。系統の経路が変わった月は、式が合わなくなって手で直します。
(b)来月の見込みが書けない。 4番目と5番目は、前年の同じ月と比べるだけです。今年は学校の始業日が違う、祝日が曜日を移った、駅前の商業施設が閉店した、といった違いを、担当の記憶で足し引きしています。 根拠を聞かれても、数字で答えられません。
(c)候補の選び方が人によって違う。 定員の何割を超えたら「混んでいる」とするか、何人を下回ったら「空いている」とするかが決まっていません。同じ表を見ても、課長と若い担当で拾う便が違います。
(d)苦情の多い便から先に手を付けてしまう。 混雑の苦情や減便への反対の声が届いた便は、数字を見る前に検討の対象に入ります。声の届かない系統の、本当に混んでいる便が後回しになります。
- 【自動】 毎月2日の朝、精算の仕組みから書き出された前月の乗降の記録と、運行の時刻のデータをプログラムが読み込む
- 【自動】 乗車と降車を便ごとに組み合わせ、停留所の順に車内の人数を積み上げて、便ごとの乗車の人数と最も混む区間の人数を出す
- 【自動】 系統・方向・時間帯・日の種類ごとに、翌月から3か月先までの乗客数と最も混む区間の人数を、真ん中と幅で見込む
- 【自動】 定員と運行回数に照らし、混雑の候補・閑散の候補・前年からの変化が大きい系統に印を付け、検討表を更新する
- 【人】 計画の担当が、印の付いた系統の根拠(時間帯ごとの人数、前年との差、効いた項目)を確かめ、事情を書き添える
- 【人】 課長が、運行の部門と運転士の勤務の担当に相談する便を決める
- 【人】 ダイヤの改正の案を作り、自治体との協議と運行計画の届出を進める(これまでどおり)
5番目で、担当は「表を作る」代わりに「理由を確かめる」ことに時間を使います。 印の無い系統は、見込みと前月の実績の並びを流し見て終わりにします。時間を使うのは、学校の予定の変わり目や、沿線の施設の開業・閉店のような、過去の記録から読めない事情のある系統です。
6番目と7番目を自動にしないのは、意図してのことです。 見込みが「この便は空いている」と出ても、その便が唯一の通院の足になっている人がいるかは、記録からは分かりません。 減便の判断には、乗客数の外にある事情を人が見る必要があります。
02今回想定するシステム構成
ICカードの精算の仕組み(乗降の記録の書き出し。カードの番号は書き出しの時点で置き換える) 運行の時刻のデータ(GTFS-JP:系統・便・停留所の順・時刻・運行日) 車両の定員の台帳/暦(祝日・学校の休み・沿線の行事)/過去の気象のデータ │ ▼【トリガー】毎月2日 6時(社内のサーバーで動かす) Python(pandas) ├──▶ 乗車と降車を便ごとに組み合わせ、停留所の順に車内の人数を積み上げる ├──▶ 現金の乗客の分を、系統ごとの乗降調査の割合で補う ▼ scikit-learn(HistGradientBoostingRegressor、loss="poisson" と loss="quantile") │ 系統・方向・時間帯・日の種類ごとの乗客数と最も混む区間の人数(真ん中と上側・下側) ▼ Python ── 定員・運行回数との比べ、印付け、検討表の更新 ▼ 【人が根拠を確かめ、相談する便を決める】── 計画の担当・課長 ▼ ダイヤの改正の案 ── 運行の部門・運転士の勤務の担当・自治体との協議・届出
| 役割 | 想定する製品 | 代替候補 |
|---|---|---|
| 実行環境 | Python(pandas・scikit-learn) | R |
| 処理エンジン | scikit-learn の HistGradientBoostingRegressor(ポアソン損失と分位点損失) | LightGBM、statsmodels の一般化線形モデル(ポアソン回帰) |
| 集計 | Python(車内の人数の積み上げ、定員との比べ、印付け) | 検討表の計算式 |
| データの取得元 | 精算の仕組みの書き出し、GTFS-JPのデータ、定員の台帳 | 運行の記録の帳票 |
| 結果の出力先 | 計画課の共有フォルダの検討表 | 社内の連絡の場への通知 |
精算の仕組みには、何も書き込みません。 決まった時刻に前月分の乗降の記録を書き出してもらい、カードの番号は書き出しの時点で別の記号に置き換えます。 計画課の手元には、誰が乗ったかではなく、どの便でどこからどこまで乗ったかだけが届く形にします。
便との突き合わせには、運行の時刻のデータを使います。 国土交通省は、時刻表や運賃などの運行情報を経路検索の仕組みに載せるための国際的な標準の仕様「GTFS」を国内の実情に合わせたものとして「GTFS-JP」を定めていて、最新の仕様として公共交通運行情報標準データ仕様(GTFS-JP)v4を公開しています。 2025年度に「GTFS-JPアップデート」が行われています。
GTFSの仕様では、trips.txt の trip_id が便を表し、route_id で系統に、service_id で運行日の組に結び付きます。direction_id は0と1で逆向きの運行を表します。stop_times.txt の stop_sequence は便の中の停留所の順で、便に沿って増えていけば連番でなくてよいとされています。日をまたぐ便の時刻は、24:00:00を超える値(午前1時35分なら25:35:00)で書く決まりです。この3つが、乗降の記録を便と停留所の順に並べる手がかりになります。
土台になるのは、scikit-learn の HistGradientBoostingRegressor です。 loss に poisson を選べ、その場合は目的の値が0以上である必要があります。 乗客数のような数える値に向いた損失です。loss="quantile" を選ぶと分位点(ピンボール)損失になり、quantile に0から1の値を渡して、上側・下側の幅を別のモデルで見込めます。 欠けた値(NaN)をそのまま扱え、分かれ目ごとに欠けた値を左右どちらに送るかを学ぶ作りです。
03どうやって実装するのか
処理の起点を決める
毎月2日の朝6時に動かします。 前月の末日の最終便の精算が締まり、精算の仕組みから乗降の記録が書き出された後です。計画課が月の初めの会議の前に検討表を見られる時間に間に合わせます。 書き出しの時刻は、精算の仕組みの保守の会社と決めます。
ダイヤの改正の前は、もう一度動かします。 改正の案ができたら、案の便の時刻で同じ見込みを作り直し、改正後の便ごとに、最も混む区間の人数の見込みと定員の比べを出します。改正の案そのものを作るのではなく、案の便に見込みを当てはめるだけです。
書き出しが届いていない、または件数が前月の半分を下回るときは、動かしません。 精算の仕組みの障害や書き出しの漏れで記録が欠けた月を、そのまま学ばせないためです。計画課に知らせ、保守の会社に書き出しのやり直しを頼みます。
入力データを集める
| データ | 中身 | 取得元 |
|---|---|---|
| 乗降の記録 | タッチの日時、乗車・降車の別、停留所、車両、便、カードの種類、置き換えたカードの記号 | 精算の仕組みの書き出し |
| 運行の時刻 | 系統、便、方向、停留所の順、時刻、運行日の組 | GTFS-JPのデータ |
| 車両の定員 | 車両ごとの座席と立ち席を合わせた定員、便ごとに当たる車両の型 | 定員の台帳と車両の運用表 |
| 乗降調査 | 系統ごとの現金の乗客の割合、IC以外の乗客の数 | 年1回の乗降調査の結果 |
| 暦 | 祝日、年末年始、沿線の学校の始業・終業・試験の日、病院の休診日、沿線の行事 | 内閣府の祝日の表、学校・病院の公開の予定、自社の行事の表 |
| 過去の気象 | 日ごとの降水量、最高気温、雪の有無 | 気象のデータ |
| 運行の異常 | 運休、迂回、大幅な遅れ、臨時便 | 運行管理の記録 |
質を決めるのは、学校の予定です。 通学の系統の乗客数は、学校が授業のある日かどうかでほぼ決まります。祝日の表だけでは、夏休みの始まりの日も、試験期間の早帰りも入りません。 沿線の高校・大学の年間の予定を、毎年の初めに日付の表にします。
乗降調査の割合も欠かせません。 ICカードの記録には現金の乗客が入りません。現金の割合は系統ごとに違い、高齢の乗客の多い系統ほど高くなりがちです。 年1回の乗降調査で数えた割合を、系統ごとに持ちます。
データの取得方法を決める
精算の仕組みからは、決まった列の並びで、1か月分の乗降の記録をファイルに書き出す設定を作ります。書き出しは保守の会社の作業になることが多いので、列の並びとカードの番号の置き換えの方法を、最初に取り決めます。
| 取るもの | どこから | 何に使うか |
|---|---|---|
| 乗車と降車のタッチ | 精算の仕組みの書き出し | 便ごとの乗車の人数と車内の人数 |
| 便・停留所の順・時刻 | GTFS-JPの trips.txt・stop_times.txt | タッチを便と区間に当てる |
| 運行日の組 | GTFS-JPの calendar.txt・calendar_dates.txt | 日の種類(平日・土曜・休日・特別ダイヤ) |
| 定員 | 定員の台帳と車両の運用表 | 定員との比べ |
| 現金の割合 | 乗降調査の結果 | ICカード以外の乗客の補い |
GTFS-JPのデータは、改正のたびに版を残します。 前年の同じ月と比べるには、前年の便と今年の便がどう対応するかが要ります。便の番号は改正で振り直されることがあるので、系統・方向・始発の停留所の発車の時刻の時間帯で対応を取ります。
カードの番号の置き換えは、月ごとに鍵を変えません。 同じカードが翌月も同じ記号になるようにしておくと、定期券の乗客が何月から乗らなくなったかを数えられます。ただし、計画課は記号から人を割り出せず、置き換えの鍵は精算の仕組みの側だけが持ちます。
AIへ渡す前に整形する
- 乗車と降車を組み合わせる … 同じ記号のカードの、同じ便での乗車と降車を1つの乗車にします。降車のタッチが無いもの(タッチの忘れ、精算の失敗)は、別に数えます
- 便に当てる … タッチの車両と時刻から便を決め、停留所を
stop_sequenceの順に並べます。日をまたぐ便は24時を超える時刻で扱います - 車内の人数を積み上げる … 便ごとに、停留所の順に「乗車 − 降車」を足していき、区間ごとの車内の人数を出します。いちばん大きい区間が、その便の最も混む区間です
- 現金の乗客を補う … ICカードの人数を、系統ごとの現金の割合で割り戻します。割り戻した値と元の値は別の列に持ちます
- 異常の日を外す … 運休・迂回・大幅な遅れ・臨時便の日を、運行管理の記録から印にします
- 時間帯に束ねる … 始発の停留所の発車の時刻で1時間ごとに束ね、系統・方向・時間帯・日ごとの乗客数と、その時間帯の便の最も混む区間の人数の最大を作ります
- 項目を作る … 曜日、日の種類、祝日、学校の授業の有無、試験期間、年末年始、降水量、雪、前年の同じ週の乗客数、その時間帯の便の数
3番目を正しく作るのが、この構成の土台です。 降車のタッチが無い乗車を「その便の終点まで乗った」と扱うと、終点に近い区間の車内の人数が多めに出ます。 降車の無いものは、その系統の区間ごとの降車の割合で振り分け、振り分けた数は別に残します。
7番目に「その時間帯の便の数」を入れるのは、便を減らした月の乗客数の減りを、需要の減りと取り違えないためです。 1時間に3便から2便に減らせば、その時間帯の乗客数は便の数とともに動きます。便の数を項目に入れておくと、改正の案の便の数で見込みを作り直せます。
AIに処理させる
させるのは、系統・方向・時間帯・日の種類ごとに、翌月から3か月先までの乗客数と最も混む区間の人数を、真ん中と幅で見込むことだけです。 定員との比べ、印付け、候補の並べ替えは、決まった計算で行います。
| 見込むもの | 使うもの | 判断できないときの扱い |
|---|---|---|
| 時間帯ごとの乗客数(真ん中) | 過去の乗客数、曜日、日の種類、学校の授業の有無、祝日、降水量、便の数、前年の同じ週 | 学習の記録が1年に満たない系統は short_history |
| 最も混む区間の人数(上側・下側) | 同上を分位点の損失で | 上側が定員を超える便は crowd |
| 前年からの変化 | 真ん中と前年の同じ月の実績 | 15%以上の変化は shift |
真ん中はポアソン損失、幅は分位点の損失で、別々のモデルにします。 乗客数は0以上の数える値で、時間帯によっては1便に数人という少ない数になります。二乗の誤差で学ばせると、少ない時間帯で見込みがマイナスに振れることがあります。 混雑の判断には上側を使うので、上側は quantile=0.9 のモデルで見込みます。
| させないこと | 理由 |
|---|---|
| 増便・減便・時刻の移動の決定 | 乗客数の外にある事情(通院・通学の唯一の足かどうか)を人が見る |
| 改正後の乗客の乗り換わりの推測 | 便を動かした後に乗客がどの便へ移るかは、過去の記録からは分からない |
| 個人の乗り方の追跡 | 計画に要るのは便と区間の人数だけ。記号から人をたどらない |
| 現金の乗客の推測の上書き | 乗降調査の割合をそのまま使い、勝手に足し引きしない |
| 運転士の勤務の割り当て | 勤務の担当が、労働時間の決まりに沿って組む |
2行目がいちばん起きやすい失敗です。 「7時台の便を7時15分に動かしたら何人乗るか」を見込みたくなりますが、記録にあるのは、いまの時刻で乗った人だけです。 時刻を動かした後の乗り換わりを数字で出すと、根拠の無い数字が検討表に並びます。改正の案に当てはめるのは、便の数が変わった時間帯の、時間帯全体の乗客数までにします。
指示内容を固定する
この構成は生成AIを使わないので、プロンプトの代わりに、モデルの設定と計算の規則を書いておきます。
【モデル(全系統で1つ。系統・方向は項目として持つ)】
- scikit-learn の HistGradientBoostingRegressor
・真ん中 … loss="poisson"
・上側 … loss="quantile", quantile=0.9
・下側 … loss="quantile", quantile=0.1
・categorical_features = [系統, 方向, 日の種類, 時間帯]
(pandas の category 型にしておく)
・目的の値 = 時間帯ごとの乗客数(現金の補い後)
と、時間帯の便の最も混む区間の人数の最大
- 学ばせる記録 = 過去3年。異常の日の印のある日は外す
- 学ばせ直しは毎月。確かめは直近3か月を外して学ばせ、外した3か月で見る
【見込みの作り方】
- 翌月から3か月先までの日ごとの暦と、平年並みの気象の値を項目にする
- 便の数は現行のダイヤの値。改正の案があるときは案の値でも作る
- 日ごとの見込みを、日の種類ごとの1日あたりの平均に直す
【印を付ける条件】
- crowd … 最も混む区間の上側が、その便の車両の定員の90%以上
- sparse … 時間帯の便の1便あたりの乗客数の真ん中が5人未満
- shift … 真ん中が前年の同じ月の実績から15%以上違う
- short_history … 学ばせる記録が12か月に満たない(新しい系統・経路の変更)
- no_alight … 降車のタッチが無い乗車が、その系統の乗車の10%超
- 印の無い系統は、見込みと前月の実績を並べて検討表に載せる
定員の90%、5人未満、15%という線は、計画課が決める値です。 線を設定の表に置き、プログラムには書き込みません。線を変えたら、いつ誰が変えたかを残します。 線が変わると、同じ見込みでも拾われる便が変わるからです。
quantile=0.9 を混雑の判断に使うのは、10日に1日の混み方まで見るためです。 真ん中で比べると、雨の日や試験期間の初日にだけ積み残しが出る便を拾えません。積み残しは平均の日ではなく混む日に起きます。
出力形式を固定する
系統・方向・時間帯・日の種類ごとに、次の形のJSONを作り、表にして検討表に載せます。
{
"route": "",
"direction": 0,
"day_type": "weekday | saturday | holiday | school_off",
"hour_band": "07",
"month": "",
"trips_in_band": 0,
"riders": { "p50": 0, "p10": 0, "p90": 0 },
"peak_load": { "p50": 0, "p90": 0, "capacity": 0, "peak_segment": "" },
"last_year_same_month": 0,
"ic_share_used": 0,
"flags": ["crowd | sparse | shift | short_history | no_alight"],
"top_factors": [""],
"model_version": "",
"planner_note": ""
}
1つ目の理由は、peak_segment で「どこで混むか」を示せることです。 便全体の人数だけでは、どの停留所の間で立ち客が出るかが分かりません。混む区間が駅の手前の数停留所に限られるなら、区間便という選び方も検討できます。
2つ目は、ic_share_used で補いの前提を残せることです。 見込みは現金の割合で割り戻した値なので、乗降調査の割合が古いと、見込み全体がずれます。 どの割合を使ったかを並べておけば、調査をやり直すべき系統が分かります。
3つ目は、planner_note に担当の書き添えを残せることです。 「4月から沿線の高校が移転」「病院の外来の曜日が変わる」のように、記録に無い事情を担当が書けば、それが翌年の暦の項目の候補になります。
システムへ連携する
| つなぎ先 | 方式 | 内容 |
|---|---|---|
| ICカードの精算の仕組み | 月1回の書き出しの受け取り | 乗降の記録(カードの番号は置き換え済み) |
| 運行の時刻のデータ | GTFS-JPのファイルの読み込み | 系統・便・停留所の順・運行日 |
| 定員の台帳 | 表の読み込み | 車両ごとの定員、便に当たる車両の型 |
| 運行管理の記録 | 表の読み込み | 運休・迂回・臨時便の日 |
| 計画課の検討表 | 共有フォルダへの書き出し | 見込み、印、根拠 |
| 社内の連絡の場 | 通知 | 印の付いた系統の数と検討表の場所 |
運行の時刻のデータにも、何も書き戻しません。 改正の案の便の時刻は、計画課が自分で作ったGTFS-JPの案のファイルから読みます。見込みから時刻を書き換える経路は作りません。
通知には乗客数の数字を流しません。 流すのは「crowd が何便、sparse が何便」と検討表の場所だけにし、乗降の記録から作った数字が連絡の場の外へ写される経路を作りません。
人が確認する
計画の担当が見るのは、印の付いた系統の根拠です。 印の無い系統は、見込みと前月の実績の並びを流し見て終わりにします。全系統の表を前の方法で作り直す運用にすると、第10章の18.0時間には収まりません。
crowdを先に見る … 上側が定員の90%を超える便です。運行の部門に、積み残しや乗り切れない報告が実際に出ているかを確かめますshiftを見る … 前年から大きく変わった系統です。沿線の施設の開業・閉店、学校の移転、経路の変更など、記録に無い理由が無いかを確かめますsparseを見る … 乗客の少ない時間帯です。その時間帯の便が、通院や通学の唯一の足になっていないかを確かめますno_alightとshort_historyを見る … 見込みの土台が弱い系統です。検討の候補に入れる前に、乗降調査で人数を確かめます- 書き添える … 確かめた事情を
planner_noteに残します
3番目を省かないでください。 乗客数が少ない便を減らすと、その時間にしか通えない人の足が無くなります。 乗客数の見込みは、減便の候補を並べる道具であって、減便を決める道具ではありません。自治体の補助を受ける系統は、とくに地域の協議の場で確かめてから進めます。
課長が在職しているうちは、月に1回、印の無い系統も並べて見てもらいます。 見込みと課長の見立てが同じ向きにずれる系統が続くなら、モデルに入っていない手がかり(沿線の行事、病院の外来の曜日)があるということです。 その手がかりを暦の項目に足すことが、引き継ぎの中身になります。
例外に対処する
| 起きること | 対応 |
|---|---|
| 書き出しが届かない、件数が前月の半分未満 | 見込みを出さず、保守の会社に書き出しのやり直しを頼む |
| 降車のタッチが無い乗車が多い | 区間ごとの降車の割合で振り分け、no_alight を付ける |
| タッチの時刻と便が合わない(遅れ・臨時便) | 運行管理の記録で便を決め直す。決まらないものは別に数える |
| 系統の経路が変わった | 変わった日から別の系統として扱い、short_history を付ける |
| 新しい系統を走らせ始めた | 1年は担当の見立てを優先し、見込みは参考として並べる |
| 災害・大雪で運休が続いた | その期間を学ばせる記録から外し、翌月の見込みに shift を付ける |
| 沿線の大きな行事で臨時便を出した | 行事の日の印を付け、翌年の同じ行事の日の項目にする |
| 現金の割合が古い(調査から2年以上) | ic_share_used を検討表で目立たせ、乗降調査を計画する |
| 精算の仕組みを入れ替えた | 書き出しの列の並びを確かめ直し、入れ替えの前後の人数を突き合わせる |
上から2行目は、毎月必ず起きます。 降りるときのタッチを忘れる乗客、精算の機械の不調、車内の混雑で後ろの扉から降りた乗客がいます。割合が急に増えた系統は、機械の故障を疑って運行の部門に知らせます。 見込みの誤りより先に、記録の取り方の問題を直します。
記録を残す
- 読み込んだ乗降の記録の件数と、置き換えの方式の版
- 便ごとの乗車の人数、区間ごとの車内の人数、最も混む区間
- 系統・方向・時間帯・日の種類ごとの見込み(真ん中・上側・下側)と印
- 計画の担当の書き添え(
planner_note)と、候補にした・しなかった理由 - 翌月の実際の乗客数と、見込みの外れ方
- モデルの版、学ばせた期間、印の線の値
5つ目の外れ方は、系統ごとに毎月並べます。 外れが続く系統は、暦の項目が足りないか、現金の割合が古いかのどちらかです。外れ方の記録が、見込みを信用してよい系統とそうでない系統の目印になります。
04実装レベルの3段階
最小構成では、系統の数がさばけません。 1系統の表計算に半日かかるので、30系統には使えません。確かめるための段階です。 半自動化で、①の便ごとの集計の時間はほぼ無くなります。 ただし、来月以降の見込みと候補の表は手で残ります。本格構成で、担当が見るのは印の付いた系統の根拠だけになり、この段階が本記事の想定です。 差が大きいのは、学校の予定や祝日の移りを足し引きする作業が、系統ごとの手作業だからです。 段階を飛ばさないでください。 半自動化の集計を半年並べると、降車のタッチが欠けやすい系統と、現金の割合が古い系統が先に分かります。そこを直してから見込みに進むほうが、印の空振りが減ります。
05工数削減シミュレーション
導入後 60件 × 18分 ÷ 60 = 18 時間/月
自社条件で導入効果を整理したい方へ
このユースケースを自社に当てはめた場合の前提値と削減見込みを、業務ヒアリングをもとに整理します。
06向いている企業・向いていない企業
- 路線バスを30系統以上走らせ、運賃の支払いの大半がICカードで、乗車と降車の両方でカードをタッチする方式の事業者。ダイヤの見直しを年に数回行い、そのたびに計画の担当が系統ごとの乗客数を表計算で集めている場合。混雑の苦情と空いた便の減便の検討が同時に来て、どの便から手を付けるかの判断に時間がかかっている場合。運行の時刻をGTFS-JPの形で整備している場合は、便との突き合わせがさらに楽になる。
- 系統が数本で、計画の担当が全便の様子を頭に入れている場合。現金の支払いが多く、ICカードの記録が乗客の一部しか表さない場合。乗車だけをタッチする均一運賃の区間が大半で、どこで降りたかが分からない場合。なお、ダイヤの改正そのものの決定、運輸局への運行計画の届出、自治体・地域の協議会との協議は、この構成では代替できません。
07最小構成で試す方法
- 精算の仕組みから、通勤の系統を1つ選んで、過去1年の乗降の記録を書き出してもらう
- 表計算で、便ごとに停留所の順に「乗車 − 降車」を足し、最も混む区間の人数を出す
- 時間帯・日の種類ごとに、月ごとの最も混む区間の人数の平均と最大を並べる
- 車両の定員と並べ、定員の9割を超えた日が月に何日あるかを数える
- 前年の同じ月の値を「来月の見込み」とした場合の外れ方を、月ごとに数える
5番目の比べを、必ず作ってください。 これが、いま計画課が使っている見込みの土台です。Python のモデルが、これより小さい外れ方になるかで、進むかどうかを決めます。
| 出てきた内容 | 判断 |
|---|---|
| 最も混む区間が便ごとに出せ、定員を超える日が数えられる | Python で全系統の見込みに進む |
| 降車のタッチの無い乗車が多く、区間の人数が出せない | 精算の機械とタッチの案内を直すのが先 |
| 前年の同じ月で十分に当たる | 系統によっては、見込みのモデルは要らない |
2行目が出ることは珍しくありません。 失敗ではなく、便ごとの混み方を誰も数字で示せなかった理由が1つ分かったということです。 車内の案内と、降車のタッチの記録の取れ方を直してから、もう一度試してください。
08実装時につまずきやすいポイント
| 問題 | 対策 |
|---|---|
| 降車のタッチが無い乗車を終点まで乗ったと扱う | 区間ごとの降車の割合で振り分け、数を別に残す |
| 便の数を減らした月を需要の減りと読む | 時間帯の便の数を項目に入れる |
| 現金の乗客を数えない | 系統ごとの乗降調査の割合で補い、割合の年を残す |
| 二乗の誤差で学ばせ、少ない時間帯がマイナスに振れる | 真ん中は loss="poisson" で学ばせる |
| 真ん中で混雑を判断し、混む日を拾えない | 上側を quantile=0.9 で見込み、定員と比べる |
| 学校の予定を祝日の表で代用する | 沿線の学校の年間の予定を日付の表にする |
| 改正で便の番号が振り直され、前年と比べられない | 系統・方向・始発の発車の時間帯で対応を取る |
| 日をまたぐ便の時刻を翌日として扱う | 24時を超える時刻のまま扱う |
| 時刻を動かした後の乗り換わりを見込む | させない。便の数が変わった時間帯の合計までにする |
| カードの記号から人をたどれてしまう | 置き換えの鍵は精算の仕組みの側だけが持つ |
| 減便の候補をそのまま決定に使う | 候補までにし、通院・通学の足かどうかを人が確かめる |
上の3行が、この構成の外れのほとんどです。 どれもモデルの問題ではなく、記録が何を数えていて、何を数えていないかの問題です。モデルを凝らす前に、記録の欠けを数える仕組みを作ってください。
下の2行も、同じくらい早く効いてきます。 乗降の記録は、個人の移動の記録でもあります。記号から人をたどれる作りにしない、見込みで減便を決めない、の2つは、最初から決めておいてください。
09セキュリティ・AIガバナンス上の注意点
この構成で扱うデータ: ICカードの乗降の記録(日時・停留所・便・カードの種類)、運行の時刻、定員、乗降調査の結果です。カードの番号を置き換えても、乗車と降車の停留所と時刻の並びは、個人の移動に関わる情報です。
- カードの番号は書き出しの時点で置き換える … 計画課の手元に元の番号を置きません。置き換えの鍵は精算の仕組みの側だけが持ち、計画課からは引けないようにします
- 集計に要らない列を書き出さない … 定期券の区間、氏名、チャージの記録は、見込みに要りません。最初から書き出しの列に入れません
- 便より細かい単位で外に出さない … 検討表に載せるのは時間帯の人数までにし、停留所ごと・便ごとの乗降の細かい表を、協議の場の資料にそのまま出しません。少ない人数の停留所は、誰が乗ったかが推し量れるからです
- 見られる人を絞る … 乗降の記録の元のファイルは、計画課の担当に限ります
- 外部の生成AIのサービスに乗降の記録を貼り付けない … 見込みは社内のサーバーで動かします
- 減便を見込みだけで決めない … 候補までにし、利用者の事情と地域の協議を経てから、運行計画の変更として届け出ます。道路運送法は、路線定期運行を行う一般乗合旅客自動車運送事業者が運行計画を定めてあらかじめ国土交通大臣に届け出ること、変更するときもあらかじめ届け出ることを定めています
誤りが起きた場合のリスクは、混む便を見落として積み残しが続くことと、必要な便を空いていると読んで減らすことの2つです。 前者は真ん中で混雑を判断すると起き、後者は便の数や学校の予定を項目に入れずに学ばせると起きます。後者のほうが取り返しにくいので、減便の候補は必ず人が利用者の事情を確かめます。
10まず何から始めるか
1週目:書き出せる記録を確かめる
精算の仕組みの保守の会社に、降車まで含めた乗降の記録を、便と停留所の付いた形で書き出せるかを確かめます。あわせて、カードの番号の置き換えの方法と、書き出しの列を決めます。
2週目:1系統で最も混む区間を出す
第8章の手順で、通勤の系統を1つ選び、便ごとの最も混む区間の人数を表計算で出します。降車のタッチの無い乗車が何割あるかを最初に数えます。
3週目:暦の表を作る
沿線の学校の年間の予定、病院の休診日、沿線の行事を、過去3年分の日付の表にします。この表が無いと、通学の系統の見込みは当たりません。
4週目:Python で全系統の集計を出す
全系統の乗降の記録を便と区間に当て、便ごとの車内の人数を毎月出すところまで作ります。この時点では見込みを出さず、前年の同じ月との比べだけを検討表に載せます。
2か月目以降: HistGradientBoostingRegressor の見込みと印付けを足し、見込みと実際の乗客数を毎月並べて外れ方を数えます。 1件60分が何分になったかを実測し、ダイヤの改正の案に見込みを当てはめて、協議の場に数字で説明できた時点で、この構成は完成です。
11関連ユースケース
12この仕組みを理解するための記事
13技術仕様の確認日・参考情報
| 確認した内容 | 情報源 | 確認日 |
|---|---|---|
loss に poisson・quantile を選べ、poisson は目的の値が0以上である必要があること。quantile は分位点(ピンボール)損失で、0から1の値で分位点を指定すること。categorical_features の既定が from_dtype で、category 型の列を質的な項目として扱うこと。欠けた値(NaN)をそのまま扱えること。早期終了の既定(auto) | scikit-learn: HistGradientBoostingRegressor | 2026-10-27 |
trips.txt の trip_id・route_id・service_id・direction_id(0と1で逆向き)、stop_times.txt の stop_sequence が便に沿って増え連番でなくてよいこと、日をまたぐ時刻を24:00:00を超える値で書くこと、calendar.txt・calendar_dates.txt の役割 | GTFS Schedule Reference | 2026-10-27 |
| GTFS を国内の実情に合わせたものとして国土交通省が GTFS-JP を定め、普及を進めていること。最新の仕様が公共交通運行情報標準データ仕様(GTFS-JP)v4であること | 国土交通省: 公共交通運行情報標準データ(GTFS-JP)に関する資料・検討会 | 2026-10-27 |
| GTFS-JP v4 の仕様書・技術解説書・v3との差分が公開され、2025年度に「GTFS-JPアップデート」が行われたこと | 国土交通省: 公共交通運行情報標準データ仕様(GTFS-JP)v4 | 2026-10-27 |
| 路線定期運行を行う一般乗合旅客自動車運送事業者が運行計画を定めてあらかじめ国土交通大臣に届け出ること、運行計画の変更もあらかじめ届け出ること(道路運送法第15条の3) | e-Gov 法令API: 道路運送法 | 2026-10-27 |
混雑・閑散の線の値と、減便を検討するときの地域との協議の進め方は、自社の運行の方針と自治体との取り決めで決めてください。 本記事は上記の公開資料で確認できた範囲だけを扱っています。
実装ステータス:構成例。 公開仕様に基づいて設計した構成であり、当社で実際に構築・検証したものではありません。工数の数値はモデル条件による試算です。
自社の業務に使えるAI活用候補を整理します
このユースケース(UC-1986)についてのご相談はこちらから。
