Zurich Tram Data

Vom Rohdaten-Archiv zum Master-Datensatz
Data-Engineering-Pipeline für das Zürcher Tramnetz (VBZ) | 2023–2025

Engineering Deep-Dive

Werkzeugwahl, Join-Mechanik, Schema und Validierung im Detail. Für Data Engineers und Tech Leads.

38 GB
IST-Rohdaten komprimiert
~4×
Polars vs. Pandas
10 → 26
Spalten nach Anreicherung
94,4 M
Zeilen, validiert
Agenda

Inhaltsübersicht

Der technische Weg durch die Pipeline

1Ausgangssituation
2Daten Reduktion
3Daten Anreicherung
4Daten Zusammenführung
5Masterdatensatz als Resultat
6Limitierungen
7Ausblick
Ausgangssituation

Die Datenstrategie

Zusammenführung der fünf Datenquellen zu einem reproduzierbaren Master-Datensatz

Gesamte Datenpipeline
Daten Reduktion

Schweiz ÖPNV IST-Daten

38 GB schweizweite Ist-Daten als Ausgangsvolumen

38 GB
komprimierte Archiv-ZIPs
~400
Transportunternehmen CH
5
Verkehrsmittel-Arten
Die IST-Rohdaten beschreiben den gesamten öffentlichen Verkehr der Schweiz — jeder Zug, Bus, jedes Tram, Schiff, jede Seilbahn. Relevant ist ein schmaler Ausschnitt: VBZ Tram Zürich.
Daten Reduktion

Polars statt Pandas

Werkzeugwahl per Benchmark auf dem realen Datenvolumen

PandasPolarsFaktor
Ladezeit (alle Parquets)25,7 s6,6 s~4×
RAM-Verbrauch6,1 GB~1,4 GB~4×
Entscheidung: Polars für alle großen Operationen (IST, Merge). Pandas bleibt für kleine Quellen (GTFS/Meteo/Events) und als Lernreferenz.
Daten Reduktion

Benchmark im Detail

Warum Polars — und wie der Wechsel funktioniert

1
Messung auf echten Daten

Benchmark auf dem realen IST-Datensatz (~88 Mio Zeilen), nicht auf Spielzeugdaten

2
Warum Pandas anstößt

Bei dieser Größe am RAM-Limit (6,1 GB) — keine Lazy Evaluation

3
Polars-Vorteil

Query-Planung + Streaming: scan_parquet('*.parquet') liest ~1.035 Tages-Parquets als einen Datensatz

4
Brücke

pl.from_pandas() / df.to_pandas() für den Wechsel zwischen kleinen und großen Operationen

Daten Reduktion

Auf VBZ Tram

Regelbasierte Filterung von ~400 Betreibern auf das VBZ-Tramnetz

1
Betreiber & Produkt

~400 CH-Unternehmen → BETREIBER_ID 85:3849 (VBZ), PRODUKT_ID = Tram

2
Zeitraum & Format

2023–2025, nur Format v1 (v2 ab Mitte 2025 ausgeklammert)

3
Messqualität

nur REAL-GPS-Messungen; Durchfahrten & Zusatzfahrten raus

4
Ausfälle behalten

FAELLT_AUS_TF = true bewusst drin — extremster Verspätungsfall

5
Spalten

21 Rohfelder → 10 (KEEP_COLS); Delays & stop_sequence abgeleitet

~11 % der Zeilen entfernt — übrig bleiben echte, planmäßige Halte mit GPS-Zeitstempeln, plus alle Ausfälle.
Daten Anreicherung

Fahrplan (GTFS)

Soll-Fahrplan und Haltestellen-Stammdaten aus dem ZVV-Netz

Fahrplan (GTFS)
Wetter (Meteo)
Events
Stadtkreise (Geo)
Woher
  • data.stadt-zuerich.ch · ZIP/TXT · CC0
  • 3 Jahrgänge, gesamtes ZVV-Netz
Was zu tun
  • Auf VBZ-Tram-Linien filtern, 2024 als Primärreferenz
  • 10+ GTFS-Tabellen → 4 Parquets (routes, stops, shapes, trips)
Wie übernommen
  • Join über bpuic (Haltestellen-ID) → stop_name, stop_lat, stop_lon
  • +3 Spalten im Master
Daten Anreicherung

Wetter (Meteo)

Drei heterogene Quellen, konsolidiert auf Stundenbasis

Fahrplan (GTFS)
Wetter (Meteo)
Events
Stadtkreise (Geo)
Woher
  • data.stadt-zuerich.ch (UGZ, Wapo, ERZ) · CSV/Parquet · CC0
  • 3 Quellen, unterschiedliche Auflösung
Was zu tun
  • Auf ein stündliches Raster konsolidieren
  • 2 Referenzstationen: Stampfenbachstrasse (Stadtlage) + Mythenquai (Seelage)
Wie übernommen
  • floor(1h) als Join-Schlüssel zu den Tram-Zeitstempeln
  • +7 Spalten (u.a. temperature, precipitation, wind_speed, flood_intensity)
Daten Anreicherung

Events nach Größe

Fehlende Open-Data-Quelle durch eigene Recherche geschlossen

Fahrplan (GTFS)
Wetter (Meteo)
Events
Stadtkreise (Geo)
Woher
  • Keine strukturierte Open-Data-Quelle verfügbar
  • Manueller Crawl: Gemini, Perplexity, Transfermarkt
Was zu tun
  • Schwellenwert > 1.000 Besucher, Stadt Zürich, 2023–2025
  • FCZ/GC-Spiele, Street Parade, Züri Fäscht …
Wie übernommen
  • Als CSV aufgebaut, Join über das Datum
  • +4 Spalten (event_name, event_type, event_size, event_location)
Daten Anreicherung

Stadtkreise (Geo)

Räumliche Zuordnung der Haltestellen per Spatial Join

Fahrplan (GTFS)
Wetter (Meteo)
Events
Stadtkreise (Geo)
Woher
  • data.stadt-zuerich.ch · GeoJSON · CC0
  • Stadtkreis-Grenzen, sofort verwendbar
Was zu tun
  • Jeder Haltestelle ihren Stadtkreis zuordnen
Wie übernommen
  • Spatial Join (Punkt-in-Polygon) auf die GTFS-Stops → district_nr, district_name
  • +2 Spalten — bereits im Master, kein nachträglicher Join in der EDA nötig
Daten Zusammenführung

Die Join-Pipeline

Vier Quellen über drei Joins zum validierten Master

Vier Quellen → drei Joins → Qualitätsprüfung → vbz_master.parquet.

Master-Preparation Pipeline
Daten Zusammenführung

Left Join als Standard

Vollständigkeitserhalt: Fehlwerte als null statt Zeilenverlust

Left Join überall: jede Tram-Fahrt bleibt erhalten. Fehlende Werte (Sensor-Ausfall, Event-freier Tag) werden null — statt die Zeile zu löschen.
Datenverlust durch Join ist der häufigste stille Bug in Merge-Pipelines. Left Join macht ihn unmöglich.
Daten Zusammenführung

Zeitstempel als Herausforderung

Datentyp- und Zeitraster-Fallstricke beim Zusammenführen

Annahme
Zwei Parquets mit datetime-Spalten joinen einfach
Befund
Meteo via pl.from_pandas → datetime[ns], IST nativ datetime[us]. Polars wirft SchemaError beim Join auf den stundengerundeten Schlüssel. Fix: explizit auf pl.Datetime('us') casten.
Annahme
Stündliches Wetter passt direkt zu Tram-Zeitstempeln
Befund
Tram-Halte sind sekundengenau, Wetter stündlich. floor(1h) auf beiden Seiten erzeugt den gemeinsamen Join-Schlüssel.
Resultat

Der Master-Datensatz

Analysefertige, reproduzierbare Datengrundlage

94,4 M
Halt-Ereignisse
26
Spalten aus 5 Quellen
9
Notebooks, 00–08
100 %
reproduzierbar
vbz_master.parquet — eine Zeile pro Halt (~230 je Fahrt), angereichert mit Fahrplan, Wetter, Events und Stadtkreis. 1:1 reproduzierbar über die 9 Notebooks.
Resultat

Data Dictionary — 26 Spalten

Zusammensetzung nach Quelle

QuelleSpaltenBeispiele
IST (Verkehr)10operating_date, trip_id, line_name, arrival_delay, canceled, stop_sequence
GTFS (Fahrplan)3stop_name, stop_lat, stop_lon
Geo (Stadtkreis)2district_nr, district_name
Meteo (Wetter)7temperature, precipitation, wind_speed, flood_intensity
Events4event_name, event_type, event_size, event_location
Master gesamt26eine Zeile pro Halt-Ereignis
Resultat

Validierung

Validation Notebook — die Qualitätsprüfung

1
Schema

26 Spalten, erwartete Typen (date, timestamp[us], float, dictionary …)

2
Dimensionen

94.358.531 Zeilen — deckungsgleich mit dem ursprünglichen Referenz-Datensatz

3
Null-Verteilung

Left-Join-Nulls plausibel (z.B. event_* an event-freien Tagen)

4
Reproduzierbarkeit

Voller Lauf 00–08 erzeugt denselben Master — idempotent, resume-fähig

Limitierungen

Bewusste Limitierung

Dokumentierte Scope-Entscheidungen dieser Ausbaustufe

Grenze 1 · Backlog #1
trip_id ↔ GTFS nicht direkt matchbar
  • IST-FAHRT_BEZEICHNER (85:3849:…) und GTFS-trip_id (1.T0.1-10-…): 0 % Overlap
  • Richtungsspezifische Analysen & Kaskadeneffekt bräuchten eine Umlauf-basierte Brücke
Grenze 2 · Backlog #2
UMLAUF_ID beim Reduktions-Schritt verworfen
  • Wäre die direktere Brücke für Kaskadenanalyse als trip_id-Kontinuität
  • Nachträglich = volles Reprocessing ab den Roh-ZIPs
Bewusst dokumentierte Grenzen, nicht übersehene Fehler. Transparenz über Known Issues gehört zu sauberem Data Engineering.
Ausblick

Weitere Perspektiven

Erweiterungen für eine nächste Iteration

1

Format v2

Ab Ende 2025 wechselt opentransportdata.swiss auf Format v2 (großer VBZ-Fahrplanwechsel Dez 2025) — Integration in einer späteren Iteration.

2

trip_id / UMLAUF_ID-Brücke

Durchgängige Fahrt-Identität herstellen — Voraussetzung für richtungsspezifische und Kaskadenanalysen.

3

Feature-Anreicherung

Weitere abgeleitete Merkmale aus dem Master (z.B. Standzeit/Puffer je Halt) als Modellierungsgrundlage.

4

Reprocessing v2

Das Resultat: ein neu prozessierter Master v2 ab den Roh-ZIPs mit den erweiterten Feldern.

Zurich Tram Data

Vom Rohdaten-Archiv zum Master-Datensatz
Data-Engineering-Pipeline für das Zürcher Tramnetz (VBZ) | 2023–2025

Recherche · Reduktion · Anreicherung · Vereinigung
Master-Datensatz als Data-Engineering-Fundament für das Analyse-Projekt zh-tram-flow