Zum Inhalt springen

(04) Systeme / Fallstudie

aria-er

Die Zahlen stimmen mit denen der ARPAE überein.

aria-er ist eine Datenplattform zur Luftqualität in der Emilia-Romagna: Open Data der ARPAE und Wetter von Open-Meteo, von der Ingestion bis zum Dashboard. Diese Seite zeigt, wie sie gebaut ist und wie ihre Ergebnisse geprüft wurden.

Beginn
September 2026
Version
1.2.0, Oktober 2026
Team
Ein Entwickler
Code
Öffentlich, MIT

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

Das Problem

Die ARPAE veröffentlicht die Luftqualitätsmessungen der Emilia-Romagna als Open Data, aber nicht in einer Form, der man Fragen stellen kann: Stunden- und Tageswerte verteilt auf mehrere Dienste, wochenlang vorläufig und dann korrigiert, Stations-IDs, die sich von Datei zu Datei ändern.

Die Fragen sind einfach: wie oft jede Station die gesetzlichen Grenzwerte überschritten hat, ob die Luft besser wird, wie viel der Verkehr zur Hintergrundbelastung beiträgt, wie Wind und Regen den Feinstaub beeinflussen. Sie mit verlässlichen Zahlen zu beantworten, ist die Arbeit.

Rahmenbedingungen

  • Neuere Werte werden wochenlang korrigiert: Jeder Lauf verarbeitet ein Fenster von 30 Tagen neu und aktualisiert nach Station, Schadstoff und Stunde. Dasselbe Fenster zweimal ergibt dieselben Dateien.
  • Zeitstempel werden in UTC gespeichert; Tage und Jahre zählen das ganze Jahr in UTC+1, wie bei der ARPAE.
  • Gesetzliche Grenzwerte stehen in einem Seed, nie im SQL eines Modells.
  • Negative oder unmögliche Werte werden markiert, nicht verworfen.
  • Dieselben Modelle laufen auf DuckDB auf dem Laptop und auf BigQuery in der Cloud.

Architektur

Vier Komponenten mit je einer Aufgabe, verbunden über Dateien und Tabellen statt über Aufrufe: Ein Rust-Binary schreibt partitioniertes Parquet, dbt macht daraus getestete Marts, Dagster plant und prüft beides, ein Dashboard liest nur die Marts. Jede Zeile hängt nur von den Zeilen darunter ab.

  1. dashboard

    Streamlit: eine gefilterte Abfrage pro Mart, keine Geschäftslogik.

    orchestration

    Dagster: täglicher Zeitplan, monatliche Partitionen, Backfills, Prüfungen auf Aktualität und Vollständigkeit.

  2. transform

    dbt: Staging, Intermediate und Marts, mit mehr als hundert Tests.

  3. aq-ingest

    Rust-Workspace: Clients für ARPAE und Open-Meteo hinter einem Source-Trait, Wiederholungen mit Backoff.

  4. raw/

    Parquet, nach Jahr und Monat partitioniert, jede Partition atomar neu geschrieben, auf der Festplatte oder in Cloud Storage.

Ein Befehl startet alles mit Docker auf dem Laptop; das Cloud-Ziel schreibt nach Cloud Storage und baut dieselben Modelle in BigQuery.

Ein Tag Daten, von Anfang bis Ende

Die tägliche Aktualisierung:

  1. 01Dagster

    Zur geplanten Stunde startet es die Aktualisierung des laufenden Monats, ein Lauf nach dem anderen.

  2. 02Ingestor

    Er lädt die letzten 30 Tage aus dem Archiv der ARPAE und das Wetter von Open-Meteo und schreibt jeden betroffenen Monat als eine Parquet-Datei neu.

  3. 03dbt

    Es vereinheitlicht die Einheiten, entfernt Duplikate, führt die neuen Zeilen zusammen und baut die Marts neu. Ein fehlgeschlagener Test stoppt den Lauf.

  4. 04Dagster

    Seine Prüfungen warnen, wenn der neueste Wert älter als 48 Stunden ist oder die Vollständigkeit sinkt.

  5. 05Dashboard

    Es liest die Marts: Überschreitungen, Trends, Verkehr gegen Hintergrund, Wetter, Vollständigkeit.

Entscheidungen und Abwägungen

  1. 01

    Eine Partition neu schreiben, nie anhängen

    Jeder Monat ist eine Parquet-Datei, die mit den zusammengeführten Zeilen komplett neu geschrieben und atomar ersetzt wird. Ein erneuter Lauf ergibt dieselben Bytes; der Preis ist, einen Monat neu zu schreiben, um eine Stunde zu ändern, bei dieser Größe billig.

  2. 02

    Die gesetzlichen Regeln, kein einfacher Mittelwert

    Ein Tag zählt nur mit 18 gültigen Stunden, der Wert wird vor dem Vergleich mit dem Grenzwert gerundet, der Tag läuft in UTC+1. Ohne eine dieser Regeln wichen die Zählungen von denen der ARPAE ab.

  3. 03

    Markieren, nicht verwerfen

    Negative, null und unplausible Werte bleiben mit einer Markierung in den Daten und außerhalb der Aggregate. Zwei Warn-Tests halten sie sichtbar, statt sie still verschwinden zu lassen.

  4. 04

    Ein Satz Modelle, zwei Warehouses

    Das SQL, das sich zwischen DuckDB und BigQuery unterscheidet, steckt in wenigen Makros. Ein Emulator prüft die BigQuery-Version bei jedem Pull Request, und der Lauf in einem echten Projekt auf Google Cloud ergab identische Marts.

  5. 05

    Kein Streaming

    Die Quellen veröffentlichen Stunden nach der Messung und korrigieren monatelang, und jede Frage ist täglich oder gröber. Ein täglicher Batch beantwortet sie; Streaming brächte nur bewegliche Teile hinzu.

Geprüft mit der ARPAE

Jede Zählung von Überschreitungen wurde mit dem verglichen, was die ARPAE selbst veröffentlicht. Zwei Prüfungen haben den Code verändert: Beim Feinstaub stimmten die Zahlen erst, als der Tageswert vor dem Vergleich gerundet wurde, und beim Ozon stimmten 29 von 43 Stationen, bis die 8-Stunden-Fenster für jede Stunde berechnet wurden, auch für fehlende.

Jahresbericht zu den Daten 2025 des Messnetzes Bologna und Tagesbulletin vom 12. Oktober 2026.
IndikatorARPAEaria-er
Tage mit PM10 über 50 µg/m³, Porta San Felice, 2025mart_exceedances_yearly2020
Tage mit Ozon über 120 µg/m³, Via Chiarini, 2025mart_exceedances_yearly5454
Stationen mit denselben PM10-Überschreitungstagen 2026mart_exceedances_yearly6464
Stationen mit denselben Ozon-Überschreitungstagen 2026mart_exceedances_yearly4343

Ergebnisse, live

Die Diagramme unten lesen den Export, den aria-er jeden Morgen auf GitHub Pages veröffentlicht: dieselben Marts wie im Dashboard, von der Pipeline selbst aktualisiert.

Die neuesten Daten werden geladen…

Dashboard und Pipeline

Dashboard-Seite mit einem Balkendiagramm der PM10-Überschreitungstage pro Jahr, 2016 bis 2026, für drei Stationen in Bologna, und einer gestrichelten Linie beim gesetzlichen Maximum von 35.
Überschreitungen: PM10-Tage über dem Grenzwert pro Jahr in Bologna, gegen die 35, die das Gesetz erlaubt.
Dashboard-Seite mit zwei Linien der monatlichen NO2-Mittelwerte in Bologna von 2016 bis 2026, die Verkehrsstation immer über den Hintergrundstationen.
Verkehr gegen Hintergrund: monatliches NO2 in Bologna, der Anteil der Belastung, der vom Verkehr kommt.
Asset-Graph in Dagster: Das Ingestion-Asset speist die Staging-Modelle, dann die Zwischenmodelle, dann fünf Marts.
Die Lineage in Dagster, von der Ingestion bis zu den fünf Marts.

Wie es weitergeht

  • Ein täglicher Export der Marts, von der Pipeline veröffentlicht, um auf dieser Seite aktuelle Ergebnisse zu zeigen.
  • Ozon-Überschreitungen im Dreijahresmittel, wie es das Gesetz verlangt, sobald drei volle Jahre geladen sind.
  • Das Archiv in eine native BigQuery-Tabelle laden, falls es das kostenlose Lesekontingent übersteigt.

Code

Das Repository ist öffentlich, unter MIT-Lizenz. Ein einziger Befehl startet alles mit Docker und lädt zehn Jahre Daten.

Den Code auf GitHub lesenZurück zu Systeme