NYC BUS TRACKER — DATA DICTIONARY Generated by scripts/export_csv.js alongside the CSVs in this folder. Project: https://github.com/joshgreenman1973/experiments/tree/main/nyc-bus-tracker TWO SEPARATE DATA SOURCES LIVE HERE. Do not mix them. A. PERFORMANCE (speed, wait, bunching) — our own observations, collected every 5 minutes from the MTA BusTime SIRI feed since 2026-03-18. These are estimates from GPS positions, NOT official MTA performance metrics, and are computed differently from the MTA's published figures. B. RIDERSHIP (boardings) — the MTA's own Automatic Passenger Counter data, republished from data.ny.gov dataset fvdm-uavx. The MTA treats these as estimates: counters miss some riders and not every bus carries one. ---------------------------------------------------------------- weekly-system.csv One row per ISO week (source A). period ISO week, e.g. 2026-W30 start_date, end_date first and last date covered days days of data captured, out of 7 coverage_pct share of 6am-11pm ET clock-hours actually sampled comparable true when days=7 AND coverage_pct>=50 avg_speed_hour_norm_mph mph, every hour of day weighted equally <-- USE THIS to compare weeks avg_wait_hour_norm_min expected rider wait, hour-of-day normalized <-- USE THIS bunch_per_100_buses bunched pairs per 100 active buses (fleet-size normalized) avg_speed_raw_mph snapshot-weighted mean; NOT comparable across weeks avg_wait_raw_min snapshot-weighted mean; NOT comparable across weeks reliability_pct share of snapshots with more than one bus on the route (this is NOT schedule adherence) routes_with_20min_gaps_per_snap routes per snapshot showing a 20+ minute gap avg_active_buses, peak_active_buses Why "hour normalized": collection drops some hourly runs, and which hours land varies. Bus speed swings ~3 mph across the day, so raw weekly means move with the sampling mix rather than with real service. Rows below 50% coverage or under 7 days should not be compared head-to-head with full weeks. --------------------------------------------------------------- weekly-borough.csv One row per borough per week (source A). borough M = Manhattan, B = Brooklyn, Bx = Bronx, Q = Queens, S = Staten Island, X = express routes, other = unclassified avg_speed_mph, avg_wait_min, avg_buses raw weekly means of daily route means (NOT hour-normalized — directional only) bunch_pairs_per_snapshot raw count bunch_per_100_buses fleet-size normalized; use this one ----------------------------------------------------------------- weekly-routes.csv One row per route per week (source A). Same caveats as weekly-borough.csv. days_seen days that week with any observation of the route reliability_pct see note above — not schedule adherence gap20_count, gap30_count observations with a 20+ / 30+ minute gap -------------------------------------------------------- route-ridership-monthly.csv One row per route per COMPLETE calendar month (source B). total_boardings all boardings that month, every day of the week avg_weekday_boardings Monday-Friday boardings / calendar weekdays in the month. Public holidays count as weekdays, so months containing them read slightly low. Partial months are excluded entirely: the MTA series opens on 2024-09-30, and a single day divided by a full month's weekdays would read as a near-zero point. ------------------------------------------------------- stops-hourly-june2026.csv One row per bus stop, June 2026 (source B). 13,351 stops. HOUR COLUMNS ARE MONTH TOTALS, NOT DAILY AVERAGES. wd_total_h0 .. wd_total_h23 boardings summed across all weekdays of the month we_total_h0 .. we_total_h23 boardings summed across all weekend days weekday_days, weekend_days the divisors (22 and 8 for June 2026). avg weekday boardings in hour h = wd_total_h{h} / weekday_days hour MTA clock hour of the service date. Essentially all rows fall on their own calendar date; a handful (12 of 260,109 on a sample day) carry the following midnight and fold into hour 0. month_boardings/alightings whole-month totals across all 30 days m_to_subway STRAIGHT-LINE meters to the nearest of the 496 stations in the MTA Subway Stations file — not walking distance. That file includes the 21 Staten Island Railway stations, so the SIR counts as subway here. The map's "beyond the subway" layer uses 800 m: 38.3% of stops are beyond it counting the SIR, 41.5% if the SIR is excluded. in_crz 1 if inside the MTA congestion relief zone — within the Central Business District polygon and NOT within one of the excluded roadway polygons (FDR Drive, West Side Highway/Route 9A, Battery Park Underpass, Hugh L. Carey Tunnel surface connections). The source geofence file does not label its polygons; the largest is taken as the CBD and the rest as the roadways the law excludes. Juneteenth (Friday, June 19, 2026) ran holiday service but counts as a weekday. 298 stop IDs (0.63% of June boardings) had no GTFS location and are excluded. ------------------------------------------------------------------ route-classes.csv One row per bus route. bus_lane_share share of the route's shape LENGTH running within about 60 m of a marked bus lane or busway (NYC DOT ycrg-ses3). Route and lane geometry are both densified to 15 m before testing, so this is a length share, not a share of raw vertices. Proximity does not prove the route uses the lane — a lane on a cross street it merely crosses can register. cbd_relation "In CBD" / "Crossing CBD" from the MTA's own list (cgzt-smqf), or "Outside CBD" when the MTA does not list the route. Comparing route groups: bus lanes get installed where traffic is worst, so a raw speed gap between lane and non-lane routes reflects where they run at least as much as what the lanes do. Compare each group against its own past.