Teil 4 – Statistische Inferenz und medizinische Statistik
12 · Regressionsmodelle: Lineare, logistische und Cox-Regression
- Die Grundideen linearer, logistischer und Cox-Regression erklären und abgrenzen.
- Odds Ratios und Hazard Ratios korrekt interpretieren, und ihre Grenzen kennen.
- Confounder erkennen und durch Adjustierung kontrollieren.
- Modellgüte prüfen: Residuen, Kalibrierung, EPV.
- Den entscheidenden Unterschied zwischen Assoziation und Kausalität benennen.
Auf dieser Seite
Wegweiser. Dieses Modul führt vom Modell zum korrekt interpretierten Effekt.
Grundpfad (§1–§4, §6–§7). Die drei Modelltypen (linear, logistisch, Cox), wie man Koeffizienten liest, warum man für Confounder adjustiert — und die wichtigste Falle: einen Mediator nicht mitadjustieren (Overadjustment). Danach kannst du eine Regression rechnen und ihr Ergebnis sauber berichten.
Vertiefung (§5, ~20 min). Der Wahrheitsvergleich: warum eine Odds Ratio keine Hazard Ratio ist, wie wir aus dem Datengenerierungsprozess die wahren Effekte kennen, und woran man Stichprobenvarianz von echter Verzerrung unterscheidet. Lehrreich, aber zum Rechnen einer Regression nicht nötig.
Klinischer Aufhänger
Welche Faktoren sind unabhängig mit der 30-Tage-Mortalität unserer Intensivkohorte assoziiert? Alter, SOFA-Score, CRP, Diabetes und Aufnahmegrund liegen vor, und hängen alle untereinander zusammen. Eine Kreuztabelle reicht nicht: Die Regressionsanalyse betrachtet jeden Faktor unter Konstanthaltung der übrigen. Da der Datensatz synthetisch ist, kennen wir die wahren Koeffizienten und können unsere Schätzungen direkt dagegen prüfen.
1 Lineare Regression
Die lineare Regression modelliert einen stetigen Outcome als gewichtete Summe der Prädiktoren:
y = β₀ + β₁·x₁ + β₂·x₂ + … + ε
- β₀ (Intercept): erwarteter Wert, wenn alle Prädiktoren null sind.
-
βⱼ: Änderung von y pro Einheit xⱼ, ceteris paribus, d. h. alle anderen Prädiktoren bleiben konstant.
-
ε: Residuum, soll normalverteilt, unabhängig und mit konstanter Varianz (Homoskedastizität) sein.
Klinisches Beispiel: verweildauer_tage ~ sofa_score + alter. Jeder
zusätzliche SOFA-Punkt ist mit βˢᵒᶠᵃ weiteren Tagen assoziiert, adjustiert für
das Alter.
Voraussetzungen prüfen: Residuenplot (Residuen gegen Fitted Values) deckt Heteroskedastizität und Nichtlinearitäten auf; QQ-Plot prüft Normalverteilung der Residuen; VIF-Werte (> 10: Warnsignal) messen Multikollinearität.
Residuendiagnostik: Homoskedastizität vs. Heteroskedastizität
Ein Kern-Check bei linearen Regressionsmodellen ist das Zeichnen der Residuen gegen die vorhergesagten Werte (Fitted Values):
- Homoskedastizität: Die Residuen streuen als gleichmäßige Wolke um die Nulllinie. Die Modellannahme ist erfüllt.
- Heteroskedastizität: Die Residuen bilden einen Trichter (die Varianz nimmt mit größeren vorhergesagten Werten zu). Das führt zu ungenauen Standardfehlern und verfälschten p-Werten.

Verweildauer ist rechtsschief, wenige Patient:innen liegen extrem lange auf der Intensivstation. OLS ist dann illustrativ, aber verzerrt. Abhilfe: log-transformierter Outcome oder ein Gamma-GLM, das die Schiefe explizit modelliert.
Für FortgeschritteneVertiefung
Bei zählwertartigen Outcomes (z. B. Anzahl Komplikationen)
ist Poisson-Regression die natürliche Erweiterung; bei starker Overdispersion
ein negatives Binomialmodell. Beide sind in statsmodels.formula.api.glm mit
einem Zeilenunterschied umsetzbar.
2 Logistische Regression
Wenn der Outcome binär ist (verstorben: ja/nein), modelliert die logistische Regression die Log-Odds (Logit) des Ereignisses:
logit(p) = ln(p / (1−p)) = β₀ + β₁·x₁ + … + βₖ·xₖ
Die Odds Ratio (OR) für Prädiktor xⱼ ist exp(βⱼ):
| OR | Interpretation |
|---|---|
| 1,0 | kein Unterschied zur Referenz |
| 2,0 | doppelt so hohe Chance auf das Ereignis |
| 0,5 | halb so hohe Chance (protektiv) |
Ein 95-%-Konfidenzintervall für die OR, das die 1,0 nicht einschließt, zeigt statistische Signifikanz an. Die Breite des KI zeigt die Präzision, schmale KI entstehen durch große Stichproben und häufige Ereignisse.
OR ≠ relatives Risiko (RR). Bei seltenen Ereignissen (< 10 %) sind OR und RR annähernd gleich. Bei häufigeren Ereignissen überschätzt die OR das RR erheblich. In unserer Kohorte liegt die 30-Tage-Mortalität bei ~15,6 %, also bereits über der 10-%-Schwelle: OR und RR laufen hier spürbar auseinander, und die OR überschätzt das tatsächliche relative Risiko. Genau deshalb in Publikationen immer explizit „Odds Ratio" schreiben, nie „Risiko" oder „Wahrscheinlichkeit".
Kalibrierung
Ein Modell, das für 100 Patient:innen eine 30-%-Mortalität vorhersagt, sollte auch ~30 tatsächlich Sterbende zeigen. Kalibrierung prüft diese Übereinstimmung zwischen vorhergesagten Wahrscheinlichkeiten und beobachteter Ereignisrate: Hosmer-Lemeshow-Test oder, besser, eine Kalibrierungskurve (Observed vs. Predicted). Ohne Kalibrierung ist ein klinisches Prognosemodell unvollständig.
Ein Modell kann eine hohe AUC haben (gute Diskriminierung) und trotzdem schlecht kalibriert sein, die beiden Gütemaße messen verschiedene Dinge. AUC allein reicht für einen klinischen Einsatz nicht.
Für FortgeschritteneVertiefung
Die Kalibrierung verschlechtert sich regelmäßig, wenn ein in einer Kohorte entwickeltes Modell auf eine andere übertragen wird (externe Validierung, Modul 25). Rekalibrierung durch Anpassung des Intercepts ist ein etablierter erster Schritt.
3 Cox-Regression
Zählt nicht nur, ob, sondern auch wann ein Ereignis eintritt, ist die Überlebenszeitanalyse das Mittel der Wahl. Die Kaplan-Meier-Kurve zeigt den Überlebensverlauf zweier Gruppen:

Die Cox-Regression modelliert die Hazard-Funktion, das momentane Ereignisrisiko zum Zeitpunkt t, unter der Bedingung, bis dahin überlebt zu haben:
h(t) = h₀(t) · exp(β₁·x₁ + … + βₖ·xₖ)
-
h₀(t): Baseline-Hazard, wird nicht parametrisch spezifiziert (daher „semiparametrisches" Modell).
-
Hazard Ratio (HR):
exp(βⱼ), interpretiert wie die OR, aber bezogen auf das momentane Ereignisrisiko zu jedem Zeitpunkt. -
Zensierung: Patient:innen ohne Ereignis bis Studienende gehen zensiert ein. Das ist kein Datenverlust, sondern Information: „mindestens so lange überlebt". Ignorieren führt zu verzerrten Schätzungen.
Proportionale Hazards-Annahme: Die HR zwischen zwei Gruppen bleibt über die
gesamte Beobachtungszeit konstant. Prüfung: Schoenfeld-Residuen (cox.zph() in
R, check_assumptions() in lifelines) oder grafisch mit dem log-log-Plot.
Wenn sich Überlebenskurven kreuzen, ist die PH-Annahme verletzt, eine einzige HR ist dann irreführend. Abhilfe: zeitabhängige Koeffizienten oder stratifiziertes Cox-Modell (nach der verletzenden Variable stratifizieren).
Für FortgeschritteneVertiefung
Für sehr kurze Beobachtungsfenster (< 30 Tage, kaum Zensierung) liefert logistische Regression ähnliche Aussagen bei einfacherer Interpretation. Cox-Regression punktet, sobald die Beobachtungszeit variiert oder Zensierung relevant ist, also in fast allen echten klinischen Datensätzen.
Unser Datensatz enthält zwei ähnlich klingende Zeitspalten,
nur eine davon ist eine echte Ereigniszeit. verweildauer_tage
(Krankenhaus-Verweildauer) ist rein deskriptiv und unabhängig vom
Überlebensprozess generiert, sie eignet sich nicht als Cox-/KM-Zeitvariable.
fu_zeit_tage (Nachbeobachtungszeit, gekappt bei 30 Tagen) zusammen mit
status (1 = verstorben, 0 = zensiert) ist die korrekte Kombination für jede
Überlebenszeitanalyse, siehe data/README.md.
4 Confounder und Adjustierung
Ein Confounder ist eine Variable, die sowohl mit dem Prädiktor als auch mit dem Outcome assoziiert ist, und so eine scheinbare Assoziation erzeugt oder eine echte verdeckt.
Beispiel: Ältere Patient:innen haben häufiger Diabetes und eine höhere
Mortalität. Wer den Diabetes-Effekt ohne Altersjustierung schätzt, überschätzt
ihn. In unserem synthetischen Datensatz kennen wir den wahren Effekt: β = 0,45
auf der Log-Hazard-Skala, also eine wahre direkte HR von 1,55 und eine wahre
adjustierte OR von 1,71 (§5). Der rohe, unadjustierte Schätzer liegt
systematisch höher.
Die Strategie: alle bekannten und gemessenen Confounder ins Modell aufnehmen. Was nicht gemessen wurde, bleibt unkontrolliert, die fundamentale Grenze jeder Beobachtungsstudie, die kein Regressionsmodell überwindet.
Nicht alles, was mit dem Outcome korreliert, ist ein Confounder. Ein Mediator liegt auf dem kausalen Pfad zwischen Prädiktor und Outcome (z. B. Sepsis → Organversagen → Mortalität): ihn zu adjustieren würde den interessierenden Effekt wegsperren. Ein Kollider öffnet durch Adjustierung erst einen Scheinzusammenhang. Ob eine Variable Confounder, Mediator oder Kollider ist, folgt aus einem kausalen Modell (DAG), nicht aus der Korrelationsmatrix.
In unserem Datensatz ist sofa_score bewusst ein
Mediator auf dem Pfad diabetes/sepsis → sofa_score → Tod (siehe DAG
in data/README.md). Willst du den totalen Effekt von Diabetes oder
Sepsis schätzen, darfst du sofa_score nicht zusätzlich adjustieren, sonst
kontrollierst du einen Teil des interessierenden Effekts fälschlich weg
(Overadjustment-Bias).
Direkter und totaler Effekt sind zwei verschiedene Zahlen — verwechsle sie nicht. Für Sepsis (wahre Hazard Ratios, aus der Datengenerierung berechnet):
| wahre HR | was das Modell dafür enthalten muss | |
|---|---|---|
| direkter Effekt (bei festem SOFA) | 1,84 | sepsis + alter + sofa_score |
| totaler Effekt (inkl. Weg über SOFA) | 3,93 | sepsis + alter, ohne sofa_score |
Sepsis erhöht den SOFA-Score um ~3 Punkte, und jeder Punkt erhöht die Hazard. Deshalb ist der totale Effekt gut doppelt so groß wie der direkte. Wer bei der Frage „Wie viel gefährlicher ist eine Sepsis?" für den SOFA-Score adjustiert, berichtet 1,84 statt 3,93.
Am Beispiel der Verweildauer druckt code/python.py beides
nebeneinander: Sepsis verlängert den Aufenthalt um +1,21 Tage (p = 0,002) —
adjustiert man für den SOFA-Score, bleiben +0,38 Tage (p = 0,42) übrig, und
der Effekt sieht aus, als gäbe es ihn nicht.
Beim Diabetes ist derselbe Kontrast in dieser Kohorte statistisch nicht auflösbar: die geschätzte OR hat ein 95-%-KI von [0,57; 2,10]. Man kann Overadjustment-Bias hier zwar herleiten, aber nicht an 78 Ereignissen zeigen. Nutze Sepsis für die Demonstration — und misstraue jeder Lehrbuchgrafik, deren Effekt kleiner ist als ihr Konfidenzintervall.
Für FortgeschritteneVertiefung
Propensity-Score-Methoden (Matching, Gewichtung) sind eine Alternative zur direkten Adjustierung bei vielen Confoundern und ungleichen Gruppengrößen. Sie erfordern jedoch dieselbe Datengrundlage, ungemessene Confounder bleiben auch hier unkontrolliert.
Vertiefung §5 — Wahrheitsvergleich: OR ≠ HR, die wahren Effekte, Varianz vs. Verzerrung (~20 min)Vertiefung — im Grundlagen-Modus eingeklappt
5 Wahrheitsvergleich
Die Kohorte wird von einem Weibull-Hazard-Modell erzeugt
(data/generate_data.py). Dessen Koeffizienten (0,045 Alter; 0,28 SOFA; 0,45
Diabetes; 0,60 Sepsis; 0,40 aktives Rauchen) liegen damit auf der
Log-Hazard-Skala. exp(β) ist eine wahre Hazard Ratio — keine Odds
Ratio.
OR ≠ HR. Bei seltenen Ereignissen liegen sie nahe beieinander, bei 15,6 % Mortalität nicht mehr. Eine geschätzte OR gegen eine wahre HR zu halten, lässt einen unverzerrten Schätzer verzerrt aussehen.
lib/ground_truth.py spielt deshalb denselben Datengenerierungsprozess bei
N = 2 000 000 nach und schätzt dort dasselbe logistische Modell. Das liefert die
wahren Odds Ratios (relativer Monte-Carlo-Fehler < 0,5 %):
| Prädiktor | wahre HR (exp β) |
wahre OR |
|---|---|---|
| alter (pro Jahr, zentriert auf 64) | 1,046 | 1,053 |
| sofa_score | 1,320 | 1,387 |
| crp_mg_l | 1,004 | 1,004 |
| diabetes | 1,549 | 1,710 |
| sepsis (Aufnahmegrund) | 1,835 | 2,046 |
| aktiv_raucher | 1,506 | 1,601 |
Die wahren ORs liegen durchweg weiter von 1 entfernt als die HRs. Wer die HR-Spalte als „wahre OR" in einen Forest Plot zeichnet, verschiebt jede rote Raute in dieselbe Richtung.
Der Forest Plot zeigt geschätzte Odds Ratios (blaue Punkte mit 95-%-KI) und die wahren Odds Ratios (rote Rauten) nebeneinander:

code/python.py druckt für jeden Lauf, ob das 95-%-KI die wahre OR überdeckt
(nicht raten, nachrechnen!). Abweichungen sind Stichprobenvarianz, nicht
Verzerrung: bei N = 500 und 78 Ereignissen ist das KI von diabetes breiter als
der gesamte plausible Effektbereich. Zwei stabile Muster: crp_mg_l hat den
kleinsten absoluten wahren Effekt, seine relative Abweichung wirkt deshalb
oft groß. diabetes und sofa_score hängen strukturell zusammen (SOFA ist
Mediator von Diabetes, siehe §4), das macht ihre Koeffizienten instabiler als
den von alter. Bei N → ∞ konvergieren Maximum-Likelihood-Schätzer gegen die
wahren Werte (Konsistenz des MLE).
Stichprobenvarianz und Verzerrung sind verschiedene Dinge. Eine Stichprobe kann zufällig weit vom wahren Wert liegen (hohe Varianz) oder systematisch zu hoch/niedrig schätzen (Bias). Letzteres ist das Problem der Confounder-Unadjustiertheit, nicht der Stichprobengröße.
Für FortgeschritteneVertiefung
Bootstrap-Resampling illustriert die Variabilität von OR-Schätzungen empirisch: 1 000 Stichproben aus denselben Daten zeigen, wie breit die Verteilung der OR-Schätzer ist, eine intuitive Ergänzung zur analytischen 95-%-KI.
Python und R rechnen die Koeffizienten-KI mit verschiedenen
Methoden und drucken deshalb leicht abweichende Grenzen. result.conf_int()
(statsmodels) liefert Wald-Intervalle (aus dem Standardfehler, symmetrisch auf
der Log-Odds-Skala); R's confint(fit) liefert Profile-Likelihood-Intervalle.
Bei seltenen Ereignissen ist die Profile-Likelihood-Variante vorzuziehen, weil sie
die Asymmetrie der Likelihood berücksichtigt und nicht auf der Normalapproximation
beruht. Die Punktschätzer (exp(β)) sind identisch; nur die Intervallränder
unterscheiden sich.
6 In Python
Das vollständige Skript steht in code/python.py. Kernidee:
.py schreiben und mit dem ▶-Knopf in VS Code ausführen – oder Zeile für Zeile in die Python-Konsole. Setzt die in Modul 02 eingerichtete Umgebung voraus.import pandas as pd import numpy as np import statsmodels.formula.api as smf from lifelines import CoxPHFitter df = pd.read_csv("https://schradern.github.io/data-science-coach/data/kohorte.csv") df["aktiv_raucher"] = (df["raucherstatus"] == "aktiv").astype(int) df["sepsis"] = (df["aufnahmegrund"] == "Sepsis").astype(int) df["alter_z"] = df["alter"] - 64 # zentrierung wie im Generator # Logistische Regression — Odds Ratios mit 95-%-KI formula = ("verstorben_30d ~ alter_z + sofa_score + crp_mg_l " "+ diabetes + sepsis + aktiv_raucher") result = smf.logit(formula, data=df).fit(disp=False) ci = result.conf_int() print(np.exp(result.params)) # OR print(np.exp(ci)) # 95-%-KI # Cox-Regression — fu_zeit_tage/status sind die echte Ereigniszeit, # NICHT verweildauer_tage (das ist nur die deskriptive Verweildauer). cox_df = df[["fu_zeit_tage", "status", "sofa_score", "alter_z", "sepsis"]].copy() cph = CoxPHFitter() cph.fit(cox_df, duration_col="fu_zeit_tage", event_col="status") print(cph.summary[["exp(coef)", "exp(coef) lower 95%", "exp(coef) upper 95%"]])
7 In R
suppressPackageStartupMessages(library(tidyverse)) suppressPackageStartupMessages(library(survival)) df <- read_csv("https://schradern.github.io/data-science-coach/data/kohorte.csv", show_col_types = FALSE) |> mutate(aktiv_raucher = as.integer(raucherstatus == "aktiv"), sepsis = as.integer(aufnahmegrund == "Sepsis"), alter_z = alter - 64) # Logistische Regression — Odds Ratios mit 95-%-KI fit <- glm(verstorben_30d ~ alter_z + sofa_score + crp_mg_l + diabetes + sepsis + aktiv_raucher, data = df, family = binomial) exp(coef(fit)) exp(suppressMessages(confint(fit))) # Cox-Regression — fu_zeit_tage/status sind die echte Ereigniszeit, # NICHT verweildauer_tage (das ist nur die deskriptive Verweildauer). cox_fit <- coxph(Surv(fu_zeit_tage, status) ~ sofa_score + alter_z + sepsis + aktiv_raucher, data = df) summary(cox_fit)$conf.int
Wann du Hilfe holst. Sobald dein Modell mehr Prädiktoren aufnehmen soll, als du Ereignisse pro Variable hast (EPV < 10), du Interaktionen oder nicht-lineare Terme brauchst, oder unklar ist, ob eine Variable Confounder oder Mediator ist, zieh eine Statistikerin hinzu — über das Ergebnis entscheidet die Modellspezifikation, nicht der Code.
Fallstricke und Merksätze
-
Assoziation ≠ Kausalität. Kein Regressionsmodell auf Beobachtungsdaten beweist Kausalität, egal wie viele Confounder adjustiert wurden.
-
EPV ≥ 10. Faustregel: mindestens 10 Ereignisse pro Prädiktor im Modell. Mit 78 Ereignissen und 6 Prädiktoren in unserer Kohorte ergibt das EPV ≈ 13, solide über der Faustregel.
-
Multikollinearität bläht Standardfehler auf und macht Koeffizienten instabil. VIF > 10 ist ein Warnsignal; VIF 5–10 ist zu beobachten.
-
Complete Separation: Wenn ein Prädiktor das Outcome perfekt trennt, konvergiert die logistische Regression nicht, Koeffizienten laufen gegen ±∞. Lösung: Firth-Regression oder regularisierte Regression.
-
OR bei häufigen Ereignissen überschätzt das RR. Immer explizit „Odds Ratio" formulieren, nie „Risiko" oder „Wahrscheinlichkeit".
-
Kalibrierung nicht vergessen. Hohe AUC und gute Kalibrierung sind unabhängige Qualitätsmerkmale, beide sind klinisch relevant.