Ir al contenido

(04) Sistemas / Caso de estudio

aria-er

Las cifras coinciden con las de ARPAE.

aria-er es una plataforma de datos sobre la calidad del aire en Emilia-Romaña: datos abiertos de ARPAE y meteorología de Open-Meteo, de la ingesta al dashboard. Esta página muestra cómo está hecha y cómo se verificaron sus resultados.

Inicio
Septiembre de 2026
Versión
1.2.0, octubre de 2026
Equipo
Un desarrollador
Código
Público, MIT

Rust · dbt · DuckDB · BigQuery · Dagster · Streamlit · Terraform · Docker

El problema

ARPAE publica las mediciones de la calidad del aire de Emilia-Romaña como datos abiertos, pero no en una forma a la que se le puedan hacer preguntas: valores horarios y diarios repartidos en varios servicios, provisionales durante semanas y luego corregidos, identificadores de estación que cambian de un archivo a otro.

Las preguntas son sencillas: cuántas veces cada estación superó los límites legales, si el aire está mejorando, cuánto añade el tráfico a la contaminación de fondo, cómo influyen el viento y la lluvia en las PM10. Responderlas con cifras fiables es el trabajo.

Restricciones

  • Los valores recientes se corrigen durante semanas: cada ejecución reprocesa una ventana de 30 días y actualiza por estación, contaminante y hora. Repetir la misma ventana produce los mismos archivos.
  • Las marcas de tiempo se guardan en UTC; días y años se cuentan en UTC+1 todo el año, como hace ARPAE.
  • Los límites legales están en un seed, nunca en el SQL de un modelo.
  • Los valores negativos o imposibles se marcan, no se descartan.
  • Los mismos modelos se ejecutan en DuckDB en un portátil y en BigQuery en la nube.

Arquitectura

Cuatro componentes, cada uno con una tarea, unidos por archivos y tablas en lugar de llamadas: un binario en Rust escribe Parquet particionado, dbt lo convierte en marts probados, Dagster planifica y controla ambos, y un dashboard solo lee los marts. Cada fila depende solo de las de abajo.

  1. dashboard

    Streamlit: una consulta filtrada por mart, sin lógica de negocio.

    orchestration

    Dagster: planificación diaria, particiones mensuales, backfills, controles de frescura y completitud.

  2. transform

    dbt: staging, intermediate y marts, con más de cien tests.

  3. aq-ingest

    Workspace de Rust: clientes de ARPAE y Open-Meteo detrás de un trait de fuente, reintentos con backoff.

  4. raw/

    Parquet particionado por año y mes, cada partición reescrita de forma atómica, en disco o en Cloud Storage.

Un comando arranca todo con Docker en un portátil; el destino en la nube escribe en Cloud Storage y construye los mismos modelos en BigQuery.

Un día de datos, de principio a fin

La actualización diaria:

  1. 01Dagster

    A la hora prevista lanza la actualización del mes en curso, una ejecución cada vez.

  2. 02Ingestor

    Descarga los últimos 30 días del archivo de ARPAE y la meteorología de Open-Meteo, y reescribe cada mes afectado como un único archivo Parquet.

  3. 03dbt

    Normaliza las unidades, quita duplicados, fusiona las filas nuevas y reconstruye los marts. Un test que falla detiene la ejecución.

  4. 04Dagster

    Sus controles avisan cuando el último valor tiene más de 48 horas o cuando la completitud baja.

  5. 05Dashboard

    Lee los marts: superaciones, tendencias, tráfico frente a fondo, meteorología, completitud.

Decisiones y compromisos

  1. 01

    Reescribir una partición, nunca añadir

    Cada mes es un archivo Parquet, reescrito entero con las filas fusionadas y sustituido de forma atómica. Repetir una ventana da los mismos bytes; el precio es reescribir un mes para cambiar una hora, poco a este tamaño.

  2. 02

    Las reglas legales, no una media cualquiera

    Un día cuenta solo con 18 horas válidas, el valor se redondea antes de compararlo con el límite, el día va en UTC+1. Sin cualquiera de ellas, los recuentos no coincidían con los de ARPAE.

  3. 03

    Marcar, no descartar

    Los valores negativos, nulos o inverosímiles se quedan en los datos con una marca y fuera de los agregados. Dos tests de aviso los mantienen visibles en lugar de hacerlos desaparecer en silencio.

  4. 04

    Un solo conjunto de modelos, dos almacenes

    El SQL que cambia entre DuckDB y BigQuery está en unas pocas macros. Un emulador comprueba la versión de BigQuery en cada pull request, y la ejecución en un proyecto real de Google Cloud dio marts idénticos.

  5. 05

    Sin streaming

    Las fuentes publican horas después de medir y corrigen durante meses, y cada pregunta es diaria o más amplia. Basta un lote diario; el streaming solo añadiría piezas móviles.

Verificado con ARPAE

Cada recuento de superaciones se comparó con lo que publica ARPAE. Dos comprobaciones cambiaron el código: las PM10 coincidieron solo al redondear el valor diario antes de compararlo, y el ozono coincidía en 29 estaciones de 43 hasta que las ventanas de 8 horas se calcularon sobre cada hora, también las que faltan.

Informe anual sobre los datos de 2025 de la red de Bolonia y boletín diario del 12 de octubre de 2026.
IndicadorARPAEaria-er
Días de PM10 por encima de 50 µg/m³, Porta San Felice, 2025mart_exceedances_yearly2020
Días de ozono por encima de 120 µg/m³, Via Chiarini, 2025mart_exceedances_yearly5454
Estaciones con los mismos días de superación de PM10 en 2026mart_exceedances_yearly6464
Estaciones con los mismos días de superación de ozono en 2026mart_exceedances_yearly4343

Resultados en directo

Los gráficos de abajo leen la exportación que aria-er publica cada mañana en GitHub Pages: los mismos marts del dashboard, actualizados por el propio pipeline.

Cargando los últimos datos…

Dashboard y pipeline

Página del dashboard con un gráfico de barras de los días de superación de PM10 por año, de 2016 a 2026, en tres estaciones de Bolonia, y una línea discontinua en el máximo legal de 35.
Superaciones: días de PM10 por encima del límite por año en Bolonia, frente a los 35 que permite la ley.
Página del dashboard con dos líneas de medias mensuales de NO2 en Bolonia de 2016 a 2026, la estación de tráfico siempre por encima de las de fondo.
Tráfico frente a fondo: NO2 mensual en Bolonia, la parte de la contaminación que viene del tráfico.
Grafo de assets en Dagster: el asset de ingesta alimenta los modelos de staging, luego los intermedios, luego cinco marts.
El linaje en Dagster, de la ingesta a los cinco marts.

Lo que viene

  • Una exportación diaria de los marts publicada por el pipeline, para mostrar resultados al día en esta página.
  • Superaciones de ozono como media de tres años, como pide la ley, cuando haya tres años completos cargados.
  • Cargar el archivo en una tabla nativa de BigQuery, si llegara a superar la cuota gratuita de lecturas.

Código

El repositorio es público, con licencia MIT. Un solo comando arranca todo con Docker y carga diez años de datos.

Leer el código en GitHubVolver a Sistemas