The Case of the Missing 18:00 Bus: Investigating London’s Ghost Buses
DATA ANALYTICA: VOL. 1
It’s 6pm outside Victoria Station. Cold and damp, the kind of evening where you just want to get home. The countdown board says the 38 is three minutes away.
Two minutes later, it says one minute.
Then it says nothing at all. No “arriving,” no “delayed.” The bus is just gone.
Anyone who’s lived in London knows this feeling. You chalk it up to bad luck, pull your coat tighter, and wait for the next one. But I couldn’t let it go. Where does a bus actually go when it disappears from the app? Is the bus really missing, or is it the data that’s missing?
So I built a script to find out. Using Python, I polled Transport for London’s live API every few seconds during evening rush hour on Route 38, logging every prediction the system made. I wanted to catch a ghost bus in the act.
Finding where the ghosts live
Ghost buses aren’t evenly spread across London; they cluster. To find their favorite haunts, I logged coordinates across the whole route and mapped them with GeoPandas.
One spot lit up immediately: Wilton Street, just by Victoria Station.
It’s not hard to see why. At rush hour, Wilton Street turns into a bottleneck: taxis cutting across lanes, commuters spilling out of the station, buses barely able to move. That’s a familiar London traffic story. The more interesting question was how a traffic jam on the street was turning into a full disappearance on the app.
Following one bus: LTZ1536
To answer that, I needed to follow a single vehicle from the moment it entered the danger zone. I picked out LTZ1536, a double-decker heading straight into the Wilton Street crush, and pulled its full prediction history, every estimate the API gave for its arrival time, second by second.
If the system were working normally, this would be a clean, steady countdown: 13 minutes, 12, 11, and so on, down to zero.
Instead, I got a jagged, erratic mess.
The bus counted down normally at first, from 13 minutes to 6. Then, without warning, its predicted arrival time jumped back up to 30 minutes as if it had suddenly reversed down the road. A few minutes later it swung the other way, dropping all the way to zero, as though it had already arrived. It hadn’t. The system corrected itself, jumped back up to 24 minutes, and counted down again to 9 and then vanished from the data entirely.
Get Garvit akar’s stories in your inbox
Join Medium for free to get updates from this writer.
LTZ1536 didn’t disappear into thin air. The prediction algorithm behind it lost confidence, reassigned trip IDs, flailed between estimates, and eventually gave up trying to track it at all.
Why the algorithm was panicking
To understand how much strain the system was under, I looked at something simple: how much real time it took the algorithm to register one minute of progress.
Under normal conditions, this is close to a 1:1 ratio; one minute of wall-clock time roughly matches one minute of predicted progress. Near Wilton Street, that ratio fell apart. The algorithm was rewriting its own timeline in real time, trying to reconcile a bus stuck in gridlock with a model that assumed steady movement. It wasn’t just predicting badly; it was actively fighting the traffic to keep its numbers coherent and losing.
The missing data behind the missing bus
That still left one question unanswered: was this purely a software problem, or was the bus’s data connection itself dropping out?
I grouped the raw scrape data into one-minute windows and measured how consistently each bus reported in, what I’ll call its stream completeness. Healthy buses on the same route, at the same time, reported in almost perfectly: close to 100% of expected updates.
LTZ1536 didn’t. Its completeness sagged to around 90% during the exact window it went haywire.
That’s the real smoking gun. When gridlock forces a controller to make a snap decision, turning a bus around early, pulling it for a driver swap, or rerouting it, the vehicle’s telemetry connection drops along with it. The traffic jam on the street becomes a data outage in the system.
LTZ1356, indicating dropped updates prior to signal loss.So what actually is a ghost bus?
It’s the moment of physical London: the traffic, the crowds, and the chaos outside Victoria overwhelm the digital model trying to represent it. As data drops out and predictions swing wildly between zero and thirty minutes, the system eventually just gives up and erases the bus from the board, leaving you standing at the stop with nothing to look at but an empty street.
It’s a good reminder that “smart city” infrastructure isn’t really about how many sensors or predictions you throw at a problem. It’s about whether the system can stay coherent when reality stops behaving the way the model expects.
The 38 did eventually show up, by the way. Fifteen minutes late, packed to the gills, but real.
Methodology & tools: Python 3, Jupyter Notebook · TfL REST API polling via requests · pandas for time-series cleaning · geopandas and matplotlib/seaborn for spatial and trend visualization.
Source code: https://github.com/garvit26/Data_Analytica/tree/main/London_ghost_bus






