Carlos León
Todos los proyectos

Data products

Madrid NO₂ Forecasting

Previsión de NO₂ por estación en Madrid a 1, 24 y 72 horas, sin fugas de información.

Año
2026
Rol
Data & ML Engineer
Madrid NO₂ Forecasting screenshot

El problema

La mayoría de portfolios de forecasting inflan sus resultados filtrando información del futuro en las features o evaluando con splits aleatorios. Yo quería lo contrario: una evaluación de series temporales honesta y reproducible sobre los datos oficiales de calidad del aire de Madrid, donde cada afirmación corresponde a una comprobación ejecutable.

Qué construí

Un pipeline de principio a fin: ingesta tipada en Python de Madrid Open Data (más de 1,6 millones de observaciones horarias, de 2018 a 2025), marts en PostgreSQL modelados con dbt, feature engineering sin fugas, backtesting rolling-origin con embargo temporal y un modelo XGBoost directo por horizonte con intervalos conformales P10 a P90.

  1. 01Madrid Open Data
  2. 02Python Ingestion
  3. 03PostgreSQL
  4. 04dbt
  5. 05Leakage-safe Features
  6. 06XGBoost
  7. 07Rolling-origin Backtest

Cómo está hecho

  • La ingesta tipada en Python normaliza los datos oficiales de Madrid y los archivos de Open-Meteo en Parquet particionado y un esquema raw en PostgreSQL, con normalización a UTC y gestión explícita del cambio de hora.
  • dbt se encarga del grano analítico y la calidad del dato en las capas staging, intermediate y mart. Python se encarga de features, backtesting, entrenamiento y predicción.
  • Las features se limitan al momento de la predicción (solo lags y estadísticas móviles desplazadas), y hay tests de pytest que fallan si entra información del futuro.
  • Los backtests rolling-origin comparan XGBoost por horizonte contra baselines estacionales ingenuos, con manifiestos de benchmark versionados que protegen las métricas publicadas.

Resultados

  • Un 50% menos de MAE que el mejor baseline ingenuo a 1 hora, y mejoras honestas y modestas de ~12% a 24 y 72 horas.
  • Un clon limpio reproduce la demo con un solo comando, y la CI ejecuta la integración real con PostgreSQL y dbt en cada push.
  • Las previsiones incluyen intervalos conformales empíricos, reportados por su peor fold y no por la media.

Siguientes pasos

Añadir features de previsiones meteorológicas archivadas (que sí se conocían en el momento de predecir) y calibración conformal adaptativa para corregir la infracobertura en los folds de cambio de estación.

Stack

  • Python
  • PostgreSQL
  • dbt
  • XGBoost
  • pytest
  • uv
  • Docker
  • GitHub Actions

Siguiente proyecto

Chicago Taxi Trips vs Weather