Home Accueil / Blog / Statistics Statistiques

Kaplan-Meier vs Cox regression:
when to use which in clinical research

Kaplan-Meier vs régression de Cox :
quand utiliser lequel en recherche clinique

TL;DR

Kaplan-Meier describes survival. Cox regression explains it. They answer different questions and should be used together, not chosen between. Understanding when each is appropriate, and when Cox assumptions fail, is fundamental to survival analysis in clinical trials.

La différence fondamentale

Kaplan-Meier et la régression de Cox sont tous deux des méthodes pour analyser des données temps-jusqu'à-événement. Ils ne sont pas en compétition, ils adressent des questions de recherche différentes et devraient généralement apparaître ensemble dans un plan d'analyse d'essai clinique. KM décrit les données. Cox les explique.

Kaplan-Meier : ce qu'il montre et quand l'utiliser

library(survival); library(survminer)

km_fit <- survfit(
  Surv(time_to_event, event_occurred) ~ treatment,
  data = trial_data
)

ggsurvplot(km_fit, data = trial_data,
  risk.table = TRUE, conf.int = TRUE, pval = TRUE,
  xlab = "Temps (mois)", ylab = "Survie sans progression")

La table des sujets à risque sous la courbe est essentielle : elle montre combien de sujets sont encore suivis à chaque temps, ce qui contextualise la fiabilité des courbes.

Le test log-rank : ce qu'il teste et ne teste pas

Le test log-rank teste si les fonctions de survie de deux groupes sont identiques sur toute la période de suivi. Ce qu'il ne fait pas : estimer la magnitude de l'effet traitement. Il a une faible puissance quand les courbes se croisent, ce qui suggère un effet traitement variant dans le temps.

Cox à risques proportionnels : les suppositions clés

Le modèle Cox suppose des risques proportionnels : le hazard ratio entre groupes est constant dans le temps. Testez toujours cette supposition avec les résidus de Schoenfeld.

cox_fit <- coxph(
  Surv(time_to_event, event_occurred) ~ treatment + age + stage,
  data = trial_data
)

ph_test <- cox.zph(cox_fit)
print(ph_test)
ggcoxzph(ph_test)

Quand Cox échoue : alternatives

Quand la supposition de risques proportionnels est violée, utilisez le Restricted Mean Survival Time (RMST) : estimez la différence en survie moyenne jusqu'à un horizon temporel prédéfini. Aucune supposition de proportionnalité requise. Maintenant recommandé par de nombreux régulateurs comme complément au hazard ratio.

library(survRM2)
rmst2(time = trial_data$time_to_event,
      status = trial_data$event_occurred,
      arm = ifelse(trial_data$treatment == "Active", 1, 0),
      tau = 24)

Un guide de décision pratique

QuestionMéthode
À quoi ressemble la survie dans le temps ?Courbe Kaplan-Meier
L'effet traitement est-il significatif ?Test log-rank
Quel est le hazard ratio ajusté ?Régression de Cox
Les courbes KM se croisent-elles ?Vérifier PH, considérer RMST

À retenir

Utilisez Kaplan-Meier pour montrer les données, log-rank pour tester la significativité, Cox pour estimer la taille d'effet. Testez toujours la supposition de risques proportionnels. Si elle échoue, complétez avec le RMST. Ces outils répondent à des questions différentes.

The fundamental difference

Kaplan-Meier and Cox regression are both methods for analyzing time-to-event data. They are not competitors, they address different research questions and should usually appear together in a clinical trial analysis.

  • Kaplan-Meier estimates the survival function: the probability of not having experienced the event by time t. It is nonparametric and makes no distributional assumptions. It describes the data.
  • Cox regression estimates the hazard ratio: how much more (or less) likely subjects in one group are to experience the event at any given time, adjusting for covariates. It explains the data.

The typical analysis plan for a time-to-event endpoint: Kaplan-Meier curves for visualization and median survival estimates, log-rank test for the primary hypothesis test, Cox model for the primary effect estimate with covariate adjustment.

Kaplan-Meier: what it shows and when to use it

library(survival)
library(survminer)

# Fit Kaplan-Meier by treatment group
km_fit <- survfit(
  Surv(time_to_event, event_occurred) ~ treatment,
  data = trial_data
)

# KM plot with confidence intervals and risk table
ggsurvplot(km_fit,
  data        = trial_data,
  risk.table  = TRUE,
  conf.int    = TRUE,
  pval        = TRUE,          # log-rank p-value on plot
  pval.method = TRUE,
  palette     = c("#1a6fd4", "#e05c2a"),
  xlab        = "Time (months)",
  ylab        = "Progression-free survival",
  break.time.by = 3
)

The KM curve is your primary visualization. The risk table below the plot is essential: it shows how many subjects are still at risk at each time point, which contextualizes the reliability of the curves (wide CIs at late time points mean few subjects remain).

The log-rank test: what it does and does not test

The log-rank test tests whether the survival functions of two or more groups are identical over the entire follow-up period. It is the standard primary hypothesis test for survival endpoints in clinical trials.

What it does not do: it does not estimate the magnitude of the treatment effect, and it has low power when the survival curves cross (which suggests a time-varying treatment effect). If your curves cross, the log-rank test p-value is misleading.

survdiff(Surv(time_to_event, event_occurred) ~ treatment, data = trial_data)
# Output: chi-squared statistic, degrees of freedom, p-value

Cox proportional hazards: the key assumptions

The Cox model assumes proportional hazards: the hazard ratio between groups is constant over time. Mathematically, the survival curves on a log(-log) scale should be parallel. Practically, this means the treatment effect does not diminish or increase over time.

cox_fit <- coxph(
  Surv(time_to_event, event_occurred) ~ treatment + age + stage,
  data = trial_data
)

summary(cox_fit)
# exp(coef) gives hazard ratios
# exp(confint(cox_fit)) gives 95% CI for hazard ratios

Testing the proportional hazards assumption

Always test the proportional hazards assumption. The Schoenfeld residuals test is the standard approach:

ph_test <- cox.zph(cox_fit)
print(ph_test)
# p < 0.05 for a covariate indicates violation for that term
# p < 0.05 for GLOBAL indicates overall model violation

ggcoxzph(ph_test)  # visual: residuals should show no trend over time

If the global test is significant, you have a problem. The reported hazard ratio is an average over time, which may not represent the true treatment effect at any specific time point.

When Cox fails: alternatives

When proportional hazards assumption fails, you have several options:

  • Time-varying covariates: allow the treatment effect to change over time by interacting treatment with time in the Cox model.
  • Restricted mean survival time (RMST): estimates the difference in mean survival time up to a prespecified time horizon. No proportionality assumption required. Now recommended by many regulators as a complement to the hazard ratio.
  • Flexible parametric models: fit a smooth hazard function that can accommodate non-proportional hazards.
library(survRM2)

# RMST at 24 months
rmst2(time  = trial_data$time_to_event,
      status = trial_data$event_occurred,
      arm    = ifelse(trial_data$treatment == "Active", 1, 0),
      tau    = 24)
# Output: RMST difference, 95% CI, p-value

Reporting survival results correctly

For a regulatory submission or a peer-reviewed publication, the survival results section should contain:

  • Kaplan-Meier plot with risk table and 95% CI bands
  • Median survival times with 95% CI per group
  • Log-rank test p-value (with Bonferroni or hierarchical correction if multiple endpoints)
  • Hazard ratio with 95% CI from Cox model (adjusted for stratification factors)
  • Proportional hazards assumption test result
  • RMST analysis if PH assumption is violated or as a sensitivity analysis

A practical decision guide

QuestionMethod
What does survival look like over time?Kaplan-Meier curve
Is the treatment effect significant?Log-rank test
What is the hazard ratio, adjusted for covariates?Cox regression
Do KM curves cross?Check PH assumption, consider RMST
What is the mean survival benefit up to month 24?RMST

Key takeaway

Use Kaplan-Meier to show the data, log-rank to test significance, Cox to estimate effect size. Always test the proportional hazards assumption and report what you found. If it fails, supplement with RMST. These are not interchangeable tools: they answer different questions.

AM

Aslane Mortreau

Freelance Data & AI specialist working with pharmaceutical, biotech, and cosmetic R&D teams. Statistical modeling, analytical pipelines, and custom applications.

Spécialiste Data & IA freelance travaillant avec des équipes R&D pharmaceutiques, biotech et cosmétiques. Modélisation statistique, pipelines analytiques et applications sur mesure.