Pierre Laub endurance × creativity

Python ETL-Pipeline: Mehr als Training - Gesundheitsmetriken in meiner ETL-Pipeline - Teil 3

Python ETL-Pipeline: Mehr als Training - Gesundheitsmetriken in meiner ETL-Pipeline - Teil 3

Bisher lag der Fokus meines Data-Analytics-Projekts klar auf Trainingsdaten:
FIT-Files, Sessions, Zeitreihen, BigQuery, Dashboards.

Aber Training ist nur ein Teil der Wahrheit.

Was im Alltag mindestens genauso spannend ist:

  • Ruhepuls & Stress
  • Schlafdauer
  • Body Battery / Erholung
  • Gewicht
  • Tagesform

Diese Daten liegen bei Garmin, TrainingPeaks & Co. meist nicht in FIT-Files,
sondern in CSV-Exports – oft gebündelt in ZIP-Archiven.

Also war klar:
👉 Die bestehende Pipeline musste wachsen – ohne an Robustheit oder Idempotenz zu verlieren.


Ausgangslage: CSV ist nicht gleich CSV

Die neuen Daten kamen mit ein paar typischen Problemen:

  • Long-Format:
    Ein Messwert pro Zeile (Timestamp | Type | Value)
  • Uneinheitliche Werte:
    Manche Felder sind Zahlen, andere Strings wie
    Min : 18 / Max : 48 / Avg : 29
  • Technische Stolperfallen:
    • Alle Dateien heißen metrics.csv
    • Mehrere ZIP-Archive enthalten gleichnamige Dateien

Kurz gesagt:
CSV ist menschlich lesbar – aber nicht automatisch analysefreundlich.


Neues Datenmodell: Eine eigene metrics-Tabelle in BigQuery

Der erste Schritt war ein klares Zielschema.

In src/config.py habe ich eine neue Tabelle definiert:

  • Zeitreihen-optimiert
  • Partitioniert nach Timestamp
  • Eine Zeile = alle Metriken eines Zeitpunkts

Beispiele für Felder:

  • body_battery
  • pulse
  • sleep_hours
  • stress_level
  • weight_kilograms
  • plus automatisch abgeleitete Felder wie:
    • _min
    • _max
    • _avg

Damit ist die Tabelle analytisch deutlich näher an den FIT-Zeitreihen –
und perfekt für Vergleiche wie:

Schlafdauer vs. Trainingsumfang
Stresslevel vor Wettkämpfen
Erholung über Trainingsblöcke hinweg


Intelligentes Pivotieren: Vom Long-Format zur Analyse-Zeile

Der Kern der Erweiterung steckt im neuen CSV-Parser (src/csv_parser.py).

Die Logik:

  1. CSV wird eingelesen (Timestamp, Type, Value)
  2. Alle Zeilen mit gleichem Timestamp werden gruppiert
  3. Die Werte werden zu einem Datensatz gepivotiert
  4. Komplexe Strings werden automatisch zerlegt

Beispiel:

"Min : 18 / Max : 48 / Avg : 29"

wird zu:

  • stress_level_min = 18
  • stress_level_max = 48
  • stress_level_avg = 29

Fazit

Die ETL-Pipeline ist jetzt mehr als ein Trainings-Importer.

Sie ist ein persönisches Gesundheits-Data-Warehouse, das robuste CSV-Exporte verarbeitet, inkonsistente Daten toleriert und sich sauber erweitern lässt.

Commit: a1de95a

Der nächste logische Schritt?
Visualisierungen, die Training und Erholung zusammen denken –
und nicht getrennt, wie es die meisten Tools tun.