← lokativ.dev
Datenprojekt · Köln, 2026

Wie viele Radfahrer:innen fahren heute durch den Stadtwald?

Eine Übungsaufgabe aus einem ML-Kurs wurde zu einem kleinen Data-Engineering-Projekt: echte Kölner Zähldaten auftreiben, mit DWD-Wetterdaten und Kalenderinformationen verknüpfen, und daraus ein lineares Regressionsmodell bauen — samt aller Umwege, Sackgassen und der ein oder anderen Überraschung unterwegs.

2.175Tage, 2020–2025
19Features im finalen Modell
0,83R² auf Testdaten
±357Radfahrer:innen mittlerer Fehler
Die Ausgangsfrage

Echte Daten statt Lehrbuch-Datensatz

Der Auslöser war simpel: ein Online-Kurs zu maschinellem Lernen, und die Frage, ob man die Übungen nicht mit echten, selbst besorgten Daten statt mit sklearn- Beispieldatensätzen durchspielen könnte. Mit Bezug zu Köln, der eigenen Stadt — und mit einer Zeitkomponente, die sich lohnt zu modellieren: Wochentage, Jahreszeiten, Wetter.

Die Fahrrad-Dauerzählstelle im Stadtwald war der naheliegende Kandidat: automatisch erfasste, mehrjährige Messreihen, mit einem öffentlichen Dashboard. Nur: ein sauberer CSV-Download war nirgends zu finden.

Datenbeschaffung

Drei Quellen, drei ganz unterschiedliche Probleme

Radverkehr
Stadtwald

Das Köln-Dashboard der Eco-Counter-Zählstellen ist eine Next.js-Anwendung ohne öffentliche Daten-API. Der Weg zu den echten Tageswerten führte über die Browser-Entwicklertools: die React-Server-Components-Antwort (_rsc-Parameter) enthält die kompletten Rohdaten als eingebettetes JSON-Fragment — man muss sie nur aus dem Antworttext herausschälen, statt über eine dokumentierte Schnittstelle abzufragen.

Wetter
DWD Köln/Bonn

Deutlich kooperativer: der Deutsche Wetterdienst stellt Tageswerte (Temperatur, Niederschlag, Sonnenscheindauer, Wind) offen als ZIP-Download bereit. Die einzige Komplikation: zwischen dem rollierenden recent-Archiv (letzte 500 Tage) und dem jährlich aktualisierten historical-Archiv klaffte zeitweise eine Lücke von mehreren Wochen — erst nach einem DWD-internen Update war der Zeitraum durchgängig verfügbar.

Kalender
Feiertage, Ferien, Heimspiele

Gesetzliche Feiertage und Schulferien NRW wurden für 2020–2025 als feste Datumslisten hinterlegt (keine stabile, kostenlose API für historische Mehrjahresdaten gefunden). Als dritter Kalender-Faktor kamen später die Heimspieltage des 1. FC Köln dazu — eine Hypothese aus der Fehleranalyse, dazu gleich mehr. Karneval und der 11.11. brauchen dagegen gar keine Liste: Weiberfastnacht bis Veilchendienstag lässt sich über die Gauß'sche Osterformel für jedes beliebige Jahr direkt aus dem Datum berechnen, der Elfte im Elften sowieso.

Maximaltemperatur vs. Radverkehr, eingefärbt nach Wochentag/Wochenende — der grundsätzliche Zusammenhang war von Anfang an sichtbar, aber die Details brauchten mehrere Anläufe.
Maximaltemperatur vs. Radverkehr, eingefärbt nach Wochentag/Wochenende — der grundsätzliche Zusammenhang war von Anfang an sichtbar, aber die Details brauchten mehrere Anläufe.
Feature Engineering

Wie man Kategorien und Zyklen für lineare Regression aufbereitet

Lineare Regression nimmt jede Eingabezahl wörtlich als lineares Verhältnis — das passt nicht automatisch zu Kalenderdaten. Drei Entscheidungen waren hier zentral:

Wochentag und Monat als One-Hot statt als Zahl

Ein roher Wochentags-Code (0–6) würde dem Modell suggerieren, Sonntag sei "sechsmal so viel Wochentag" wie Montag — Unsinn, Wochentage sind nicht ordinal. Stattdessen bekommt jeder Tag eine eigene 0/1-Spalte, mit einer Referenzkategorie als Vergleichspunkt.

Jahreszeit als Kreis, nicht als Gerade

Der Tag im Jahr (1–365) hat am Jahresende einen künstlichen Sprung: der 31. Dezember und der 1. Januar liegen kalendarisch nebeneinander, numerisch aber 364 Tage auseinander. Eine Sinus/Cosinus-Kodierung bildet das Jahr stattdessen als Kreis ab.

# Tag im Jahr als Punkt auf dem Einheitskreis, nicht als rohe Zahl
doy = df["datum"].dt.dayofyear
df["doy_sin"] = np.sin(2 * np.pi * doy / 365)
df["doy_cos"] = np.cos(2 * np.pi * doy / 365)

Abgeleitete Flags statt roher Messwerte

Aus der Fehleranalyse (dazu im nächsten Abschnitt mehr) kamen zusätzliche Features: ein binäres hat_geregnet statt der reinen Millimeterzahl, eine Kälte-Schwelle (kaelte_unter_m0), und eine Interaktion aus Ferien-Flag und Wochenend-Flag.

Debugging-Log

Was beim Modellieren tatsächlich schiefging

Der ehrlichste Teil eines Datenprojekts ist selten die finale Pipeline — sondern das, was auf dem Weg dahin kaputtging und warum. Eine Auswahl der Momente, die das Modell am meisten vorangebracht haben:

BEFUND
VIF bis 445. Temperatur-Maximum, -Minimum und -Mittel gleichzeitig im Modell erklären sich gegenseitig fast vollständig. Monats-Dummies wurden deshalb komplett zugunsten der zyklischen doy_sin/cos-Kodierung entfernt — die drei Temperaturvariablen blieben zunächst trotzdem alle drin, weil die Gesamt-Vorhersagegüte kaum litt.
FALLE
Live-Rechner widerspricht sich selbst. Erst beim Spielen mit dem interaktiven Rechner unten fiel auf: Senkt man nur tn_min bei festgehaltenem tx_max, steigt die Vorhersage — physikalisch Unsinn. Grund: diese Kombination (warmer Tag, sehr kalte Nacht) kam im Trainingsdatensatz praktisch nie vor, das Modell extrapolierte. Konsequenz: tm_mittel komplett entfernt, nur tx_max und tn_min bleiben — VIF sinkt auf 36 bzw. 17, die Koeffizienten werden wieder einzeln interpretierbar.
FALLE
Negative Vorhersagen. Ein kalter Samstag in den Ferien drückte die Summe aus Wochenend-, Ferien- und Temperatur-Koeffizient unter null — ein Zählwert kann aber nie negativ sein. Klassische Extrapolation einer linearen Geraden über den beobachteten Bereich hinaus.
TEST
Interaktionsterm Wochenende × Temperatur verworfen.Die Hypothese "an warmen Wochenenden steigt der Freizeitverkehr überproportional" sah in Einzelfällen plausibel aus, war aber mit p ≈ 0,4 statistisch nicht von Zufall zu unterscheiden — zu wenige wirklich heiße Wochenendtage im Datensatz, um das verlässlich zu schätzen.
AUSREISSER
+2.500 Radfahrer:innen unterschätzt, Sonntag, Ende August. Die Suche nach diesem und ähnlichen Tagen führte auf eine neue Spur: Heimspiele des 1. FC Köln fehlten komplett im Modell.
AUSBAU
Regen nochmal verfeinert. Bislang stand nur das binäre hat_geregnet im Modell (ja/nein). Ergänzt um niederschlag_mmals eigenes, kontinuierliches Feature: jetzt gibt es sowohl einen festen Abschlag für "es regnet überhaupt" als auch einen weiteren, proportionalen Rückgang pro Millimeter — beide Koeffizienten bleiben trotz der Kombination klar signifikant (VIF je unter 3).
AUSBAU
Karneval und 11.11. fehlten noch. Nach demselben Muster wie bei den Heimspielen: Kölner Jecken-Tage sind kein Wetter-Effekt, sollten sich aber im Radverkehr zeigen. ist_karneval (Weiberfastnacht bis Veilchendienstag, über die Osterformel berechnet) und ist_elfter_elfter kamen als zwei weitere Kalender-Features dazu — beide hoch signifikant und mit kräftigem negativem Effekt: an diesen Tagen fährt Köln offenbar lieber kostümiert als mit dem Rad zur Arbeit.
Partial-Regression-Plots: für jedes Feature der bereinigte Effekt, nachdem alle anderen Features herausgerechnet wurden — die Grundlage für die Multikollinearitäts- und Kurvenform-Prüfung.
Partial-Regression-Plots: für jedes Feature der bereinigte Effekt, nachdem alle anderen Features herausgerechnet wurden — die Grundlage für die Multikollinearitäts- und Kurvenform-Prüfung.
Ergebnis

Was den Radverkehr tatsächlich erklärt

Das finale Modell — multiple lineare Regression mit 19 bereinigten Features — erreicht auf nie gesehenen Testdaten ein R² von 0,83 bei einem mittleren absoluten Fehler von rund 357 Radfahrer:innen pro Tag.

0,835R² Training
0,828R² Test
355MAE Training
357MAE Test
Koeffizienten des finalen Modells. FC-Köln-Heimspieltage schlagen stärker aus als jedes Wettermerkmal.
Koeffizienten des finalen Modells. FC-Köln-Heimspieltage schlagen stärker aus als jedes Wettermerkmal.
Überraschendster Befund

Der stärkste positive Einzeleffekt im ganzen Modell ist kein Wetter-Feature — es ist ein Heimspiel des 1. FC Köln. An Spieltagen liegt der geschätzte Radverkehr über 750 Fahrten höher als an einem sonst identischen Tag. Das RheinEnergieSTADION liegt nur wenige Minuten vom Stadtwald entfernt — ein plausibler, aber im Vorfeld nicht bedachter Zusammenhang, der erst durch die Ausreißeranalyse der Residuen auffiel.

Das zweitstärkste Muster ist weit weniger überraschend, aber ebenso klar: Samstag und Sonntag senken den erwarteten Radverkehr um 870 bis knapp 1.000 Fahrten gegenüber einem normalen Werktag — ein Hinweis darauf, dass die Zählstelle stark pendlergeprägt ist. Schulferien wirken in dieselbe Richtung und fast genauso stark wirkt mittlerweile auch Karneval (−773 Fahrten) — nur der 11.11. fällt mit −470 etwas moderater aus. Regen drückt den Radverkehr ebenfalls, während Sonnenscheindauer und die Maximaltemperatur die stärksten positiven, wettergetriebenen Effekte sind.

Vorhersage vs. tatsächlicher Wert, Testdaten.
Vorhersage vs. tatsächlicher Wert, Testdaten.
Residuenplot: keine erkennbare Trichterform.
Residuenplot: keine erkennbare Trichterform.
Statistik

Was sich wirklich belegen lässt — und was nicht

Die reinen Koeffizienten aus sklearn sagen nichts darüber, wie sicher sich das Modell bei den geschätzten Werten eigentlich ist. Für die statistische Absicherung wurde dasselbe Modell zusätzlich mit statsmodels.OLS gerechnet — das liefert Standardfehler, t-Werte, p-Werte und Konfidenzintervalle pro Koeffizient.

R² 0,835
Adj. R² 0,833
F-Statistik 459,1
Prob (F) < 0,001
Beobachtungen 1.740
Freiheitsgrade (Modell) 19
Cond. No. 360

Koeffiziententabelle (Trainingsdaten)

FeatureKoeffizientStd.-Fehlertp-Wert95%-Konfidenzintervall
const1989,0062,1132,02< 0,001[1867,2 ; 2110,8]
tx_max55,294,7611,61< 0,001[45,9 ; 64,6]
tn_min0,835,290,160,876[−9,5 ; 11,2]
niederschlag_mm−22,152,57−8,62< 0,001[−27,2 ; −17,1]
sonnenschein_h81,674,7217,31< 0,001[72,4 ; 90,9]
wind_mittel_ms−88,689,89−8,97< 0,001[−108,1 ; −69,3]
fc_koeln_heimspiel754,19134,825,59< 0,001[489,8 ; 1018,6]
ist_feiertag−439,2763,64−6,90< 0,001[−564,1 ; −314,4]
ist_ferien−813,1131,66−25,68< 0,001[−875,2 ; −751,0]
ist_karneval−772,7892,05−8,40< 0,001[−953,3 ; −592,2]
ist_elfter_elfter−469,97190,76−2,460,014[−844,1 ; −95,8]
doy_sin−74,9019,77−3,79< 0,001[−113,7 ; −36,1]
doy_cos−184,8831,07−5,95< 0,001[−245,8 ; −123,9]
wochentag_Freitag−345,4533,63−10,27< 0,001[−411,4 ; −279,5]
wochentag_Samstag−994,5836,90−26,95< 0,001[−1066,9 ; −922,2]
wochentag_Sonntag−870,8136,09−24,13< 0,001[−941,6 ; −800,0]
hat_geregnet−228,1130,04−7,60< 0,001[−287,0 ; −169,2]
ist_ferien_wochenende439,5258,907,46< 0,001[324,0 ; 555,0]
kaelte_unter_m0−61,9311,09−5,58< 0,001[−83,7 ; −40,2]
heimspiel_temp18,317,982,290,022[2,6 ; 34,0]

Rot markierte Zeile: p > 0,05, statistisch nicht verlässlich von 0 unterscheidbar. Einzig tn_min betrifft das — nachdem tm_mittel aus dem Modell entfernt wurde, bleiben nur noch tx_max und tn_min als Temperaturmaße übrig, die sich immer noch spürbar ähneln: sobald tx_maxden Haupteffekt trägt, bleibt für tn_min kaum noch unabhängige Information übrig. Mit der Ergänzung von niederschlag_mm als eigenem, kontinuierlichem Feature neben dem binären hat_geregnet ist heimspiel_temp (Interaktion aus Heimspiel und Temperatur) jetzt übrigens signifikant (p=0,022) — ein Hinweis, dass an Heimspieltagen wärmeres Wetter den Effekt zusätzlich leicht verstärkt.

Varianzinflationsfaktor (VIF)

Faustregel: VIF > 10 gilt als auffällig, VIF > 100 als stark.

FeatureVIF
tx_max35,8
tn_min17,1
wind_mittel_ms7,9
sonnenschein_h7,5
fc_koeln_heimspiel5,4
heimspiel_temp5,2
doy_cos2,9
hat_geregnet2,9
ist_ferien1,9
ist_ferien_wochenende1,7
niederschlag_mm1,7
wochentag_Samstag1,6
kaelte_unter_m01,5
doy_sin1,5
wochentag_Sonntag1,5
wochentag_Freitag1,2
ist_karneval1,1
ist_feiertag1,0
ist_elfter_elfter1,0

Deutlich besser als in der ersten Modellversion (dort standen tx_max, tn_min und tm_mittel gleichzeitig im Modell, mit VIF-Werten bis 445). Der Auslöser für die Bereinigung war übrigens nicht die VIF-Tabelle selbst, sondern der Live-Rechner weiter unten: beim Durchspielen fiel auf, dass ein Senken von tn_min bei festgehaltenem tx_max die Vorhersage erhöhte statt senkte — ein Kunstgriff, der in den echten Daten praktisch nie vorkam und den das Modell entsprechend falsch extrapolierte. Nach dem Entfernen von tm_mittel bleiben tx_max und tn_min zwar immer noch moderat korreliert (VIF 36 bzw. 17), aber deutlich im vertretbaren Bereich.

Reflexion

Grenzen der linearen Regression

Der Residuenplot zeigt keine systematische Trichterform — ein gutes Zeichen für die Grundannahmen des Modells. Trotzdem bleibt lineare Regression strukturell limitiert: sie kann keine Sättigungseffekte abbilden (irgendwann bremst auch Hitze den Radverkehr statt ihn weiter zu steigern — dieser Bereich kam 2020–2025 in Köln allerdings kaum vor, ein quadratischer Temperaturterm blieb entsprechend statistisch bedeutungslos), und sie extrapoliert jenseits des beobachteten Wertebereichs ohne jede eingebaute Vorsicht.

Für eine Vorhersage-Funktion heißt das konkret: Eingaben weit außerhalb des beobachteten Trainingsbereichs sollten eigentlich gegen eben diesen Bereich geprüft werden, bevor man dem Ergebnis traut — aktuell übernimmt das noch niemand automatisch, das ist ein offener Punkt für die nächste Ausbaustufe. Kalender-Flags wie Feiertage oder Schulferien lassen sich dagegen für jedes beliebige Datum von Hand übergeben; nur die automatische Erkennung aus den hinterlegten Listen deckt bislang nur 2020–2025 ab. Karneval und der 11.11. sind davon ausgenommen — die werden über die Osterformel direkt aus dem Datum berechnet und funktionieren deshalb für jedes beliebige Jahr, auch außerhalb des Trainingszeitraums.

Finale Feature-Liste

Was am Ende tatsächlich im Modell steckt

tx_max, tn_minTagesmaximum und -minimum der Temperatur (das Tagesmittel wurde wegen zu hoher Kollinearität mit den beiden anderen Maßen entfernt)
sonnenschein_hSonnenscheindauer in Stunden
wind_mittel_msmittlere Windgeschwindigkeit
niederschlag_mm, hat_geregnetNiederschlagsmenge in mm plus zusätzliches binäres Regen-Flag — modelliert einen festen „Es regnet“-Abschlag plus einen weiteren, proportionalen Effekt pro Millimeter
kaelte_unter_m0Frost-Schwelle, wie weit unter 0°C
doy_sin, doy_cosPosition im Jahreszyklus (zyklisch kodiert)
wochentag_Freitag/Samstag/SonntagOne-Hot, Referenz: Mo–Do zusammengefasst
ist_feiertag, ist_feriengesetzliche Feiertage und NRW-Schulferien
ist_karnevalWeiberfastnacht bis Veilchendienstag, über die Osterformel aus dem Datum berechnet
ist_elfter_elfter11.11., Kölner Sessionsauftakt
ist_ferien_wochenendeInteraktion: Ferien, die auf ein Wochenende fallen
fc_koeln_heimspiel, heimspiel_temp1. FC Köln Heimspieltag, plus Interaktion mit Temperatur
Live-Vorhersage

Das Modell selbst ausprobieren

Keine Serveranfrage, kein Backend — das lineare Modell ist nichts weiter als 19 Koeffizienten plus ein Achsenabschnitt. Der Rechner unten wertet dieselbe Formel aus, die statsmodels beim Training gelernt hat, direkt in deinem Browser. Karneval und der 11.11. werden dabei automatisch aus dem gewählten Datum berechnet, nicht manuell angehakt. Die Startwerte für Temperatur, Niederschlag, Sonnenschein und Wind kommen aus einer aktuellen Open-Meteo-Vorhersage für Köln, die beim Laden der Seite einmal serverseitig abgerufen wird — die Berechnung selbst läuft aber weiterhin komplett im Browser, und jedes Feld lässt sich frei überschreiben.

Live-Wetterdaten: Open-Meteo (Vorhersage für Köln, stündlich aktualisiert).

1.841
Geschätzte Radfahrer:innen am Stadtwald — Sonntag, 18.10.2026
⚠ Eine oder mehrere Eingaben liegen deutlich außerhalb des typischen Kölner Wertebereichs — das Modell extrapoliert hier, die Zahl ist entsprechend unsicherer.
Validierung

Wie gut stimmt das Modell mit der Realität 2026 überein?

Das Modell wurde nur mit Daten bis 2025 trainiert. Seit Jahresbeginn 2026 holt ein täglicher Job die tatsächlich gezählten Radfahrer:innen sowie die DWD-Wetterdaten und rechnet damit die Vorhersage für jeden Tag nach — hier die Gegenüberstellung mit nie gesehenen Daten.

0,843R² 2026
386MAE (Radfahrer:innen/Tag)
+42mittlere Abweichung (Ist − Vorhersage)
285verglichene Tage
01.0002.0003.0004.0005.0006.0007.000JanFebMärAprMaiJunJulAugSepOkt
━ gezählt (eco-counter) ╌ Modellvorhersage. Stand: 15.10.2026.

Die letzten 7 Tage

DatumGezähltVorhersageAbweichung
15.10.20263.5033.595−92
14.10.20263.5923.469+123
13.10.20262.6772.364+313
12.10.20263.3833.426−43
11.10.20263.4113.107+304
10.10.20261.5731.901−328
09.10.20261.4641.617−153

Köln, Stadtwald-Zählstelle · DWD Station Köln/Bonn (02667) · NRW-Schulferien & Feiertage 2020–2025
Datenaufbereitung, Modellierung und diese Seite entstanden in Zusammenarbeit mit Claude.