Isaac Martínez Ríos

← Casos de estudio← Case studies

ECOBICI: dónde faltan bicicletas y a qué horaECOBICI: where bikes run out, and when

¿Qué estaciones se quedan sin bicicletas, en qué días y horas, y cuántas bicicletas convendría mover, y desde dónde, para reducir el desabasto?

Which stations run out of bikes, on which days and at what hours, and how many bikes should be moved, and from where, to reduce shortages?

Respuesta cortaShort answer

La demanda tiene dos picos entre semana, a las 8:00 y de 17:00 a 18:00, y se concentra en estaciones que se vacían de forma sistemática. Con el rebalanceo propuesto se evitaría cerca del 22.6 % del desabasto estimado en la ventana evaluada.

Demand has two weekday peaks, at 8:00 and from 17:00 to 18:00, and it concentrates in stations that empty out systematically. The proposed rebalancing would avoid about 22.6% of the estimated shortage in the evaluated window.

Figura 1. Balance de viajes por estación, julio a septiembre de 2026. En azul, las que pierden bicicletas; en ocre, las que las acumulan y pueden donarlas. Solo aparecen las 537 estaciones que se pudieron emparejar con el feed GBFS. Figure 1. Trip balance by station, July to September 2026. Blue stations lose bikes; ochre ones pile them up and can donate them. Only the 537 stations that could be matched to the GBFS feed are shown.

Lo que encontréWhat I found

  1. Dos picos entre semana: a las 8:00 (unas 5.9 salidas por estación y hora) y de 17:00 a 18:00 (5.6–5.8). El fin de semana la demanda cae cerca de 30 %.
  2. Las estaciones que más se vacían incluyen CE-278 Mier y Pesado–Obrero Mundial, CE-703 Miguel Hidalgo–Calzada General Anaya, CE-294 Nicolás San Juan–Eje 4 Sur Xola y CE-540 Eucalipto–Ricardo Flores Magón.
  3. El modelo supera a la línea base, sobre todo en errores grandes y en sesgo. El RMSE baja 7.7 % y el sesgo pasa de −0.259 a −0.010: deja de subestimar la demanda. En horas pico el RMSE baja de 3.77 a 3.43.
  4. El rebalanceo es concreto: 117 movimientos y 594 bicicletas, de 96 estaciones donantes a 314 receptoras. El déficit estimado baja de 886.5 a 686.0 bicicletas, sin dejar a ninguna donante por debajo de su nivel de seguridad.
  5. El histórico es de muy buena calidad: solo se descartó el 0.044 % de los viajes (1,963), por duraciones fuera de rango. No hay duplicados ni fechas inválidas.
  1. Two weekday peaks: at 8:00 (about 5.9 departures per station per hour) and from 17:00 to 18:00 (5.6–5.8). On weekends demand drops by about 30%.
  2. The stations that drain the most include CE-278 Mier y Pesado–Obrero Mundial, CE-703 Miguel Hidalgo–Calzada General Anaya, CE-294 Nicolás San Juan–Eje 4 Sur Xola and CE-540 Eucalipto–Ricardo Flores Magón.
  3. The model beats the baseline, mostly on large errors and bias. RMSE drops 7.7% and bias goes from −0.259 to −0.010: it stops underestimating demand. At peak hours RMSE falls from 3.77 to 3.43.
  4. The rebalancing is concrete: 117 moves and 594 bikes, from 96 donor stations to 314 receivers. The estimated deficit drops from 886.5 to 686.0 bikes, without pushing any donor below its safety level.
  5. The trip history is very clean: only 0.044% of trips (1,963) were discarded, for out-of-range durations. No duplicates or invalid dates.

    Figura 2. Viajes promedio por estación en cada hora del día. Las franjas sombreadas marcan los picos. Figure 2. Average trips per station for each hour of the day. Shaded bands mark the peaks.
    Modelo contra línea baseModel versus baseline
    Métrica (prueba: 12–30 sep 2026)Metric (test: Sep 12–30, 2026) Línea baseBaseline ModeloModel CambioChange
    MAE (salidas por hora)MAE (departures per hour)1.5341.501−2.2 %
    RMSE2.7452.535−7.7 %
    WAPE0.5080.497−1.1 pp
    Sesgo medioMean bias−0.259−0.010casi insesgadonearly unbiased

    La partición es temporal y la prueba tiene 300,560 observaciones estación-hora.

    The split is temporal and the test set has 300,560 station-hour observations.

    Cómo lo construíHow I built it

    1. IngestaDescarga y normalización del histórico, más un colector del feed GBFS.
    2. IngestionDownload and normalization of the trip history, plus a GBFS feed collector.
    3. TransformaciónCapas en DuckDB: demanda y disponibilidad por estación y hora.
    4. TransformationDuckDB layers: demand and availability per station and hour.
    5. ModeladoLínea base estadística y un modelo de gradient boosting (LightGBM).
    6. ModelingA statistical baseline and a gradient boosting model (LightGBM).
    7. RebalanceoEmpareja donantes y receptoras cercanas respetando niveles de seguridad.
    8. RebalancingPairs nearby donors and receivers while respecting safety levels.
    9. InterfazSitio estático con datos reales y app en Streamlit con datos de muestra.
    10. InterfaceA static site with real data and a Streamlit app with sample data.

    Todo el sistema tiene pruebas y CI. Las cifras reales se reproducen descargando el histórico y corriendo run_pipeline.py --full.

    The whole system has tests and CI. The real figures are reproduced by downloading the history and running run_pipeline.py --full.

    Figura 3. Salidas promedio por estación y hora, según el día de la semana. Figure 3. Average departures per station per hour, by day of week.

    Lo que no se puede afirmarWhat this can't claim

    • Los viajes son demanda atendida. Cuando una estación ya está vacía, los intentos frustrados no se observan, así que en las estaciones que más se vacían la demanda real está subestimada.
    • La disponibilidad viene de una sola captura del feed GBFS. Todavía no permite medir "minutos sin bicicletas" ni validar faltantes reales; hacen falta capturas cada 5 minutos.
    • El emparejamiento de estaciones cubre el 79 % de las estaciones y el 54.7 % de los viajes, así que el mapa y el rebalanceo se limitan a esa cobertura.
    • El modelo no incorpora clima, tráfico ni costo de traslado, y el rebalanceo no modela rutas, tiempos ni capacidad de los vehículos.
    • Trips are served demand. When a station is already empty, failed attempts aren't observed, so true demand at the most-drained stations is underestimated.
    • Availability comes from a single GBFS snapshot. It can't yet measure "minutes without bikes" or validate real shortages; that needs snapshots every 5 minutes.
    • Station matching covers 79% of stations and 54.7% of trips, so the map and the rebalancing are limited to that coverage.
    • The model ignores weather, traffic and moving costs, and the rebalancing doesn't model routes, timing or vehicle capacity.