σ StatsDoge Causal inference workflows
10
Workflow·4 steps·branched

Confounder-adjusted survival curves for a treatment (adjustedCurves)

Source adjustedCurves — Robin Denz
Summary by StatsDoge

Replace the raw Kaplan-Meier comparison with curves de-confounded by IPTW or the g-formula, with bootstrap bands. Collapse to interpretable summaries — RMST difference up to τ, or survival probability at a clinical horizon — instead of a hazard ratio nobody reads.

1

Input · what goes in

Right-censored time-to-event data: an event time, an event/censoring indicator, a treatment, and the confounders.

Show data format & exampleHide example

Format — one row per unit: time, status (1=event, 0=censored), group (treatment), confounders x*.

library(adjustedCurves)
adj <- adjustedsurv(data=df, variable='group', ev_time='time',
                    event='status', method='iptw_km',
                    treatment_model=glm(group ~ x1 + x2, family='binomial'))
plot(adj)
2

Pipeline · the recipe ⑂ has parallel branches

↑ Click any step in the diagram to read its logic, code, assumptions & discussion.

1
Data prep

Time-to-event, treatment, confounders

Data preparation — shapes the raw inputs into what the estimator expects.

What happens here

Set up the censored outcome, the treatment, and the confounders of treatment assignment.

Formula
T=\min(T^{*},C),\qquad \delta=\mathbb 1\{T^{*}\le C\}
Reads from the input data Feeds into the final output
Key code
# time (T), status (event 1/0), group (treatment), x1,x2 (confounders)

Reference / docs ↗

Discussion on this step (0)
  • No comments on this step yet — be the first.
2
Estimation

Adjust for confounding (IPTW / g-formula)

The core estimate — where the causal quantity itself is computed.

What happens here

Weight by the inverse propensity of treatment (or standardise via an outcome model) and form a weighted survival estimate.

Formula
\hat S_a(t)=\dfrac{\sum_i rac{\mathbb 1\{A_i=a\}}{\hat\pi_i(A_i)}\,\mathbb 1\{T_i>t\}}{\sum_i rac{\mathbb 1\{A_i=a\}}{\hat\pi_i(A_i)}}
Reads from the input data Feeds into the final output
Key code
adjustedsurv(data=df, variable='group', ev_time='time',
             event='status', method='iptw_km', treatment_model=ps)

Reference / docs ↗

Discussion on this step (0)
  • No comments on this step yet — be the first.
3
Inference

Curves with confidence bands

Uncertainty quantification — standard errors, intervals, and aggregation.

What happens here

Bootstrap or asymptotic variance gives pointwise (and simultaneous) bands around each adjusted curve.

Formula
\hat S_1(t)-\hat S_0(t)\ \pm\ z_{1-\alpha/2}\,\widehat{\mathrm{se}}(t)
Reads from the input data Feeds into the final output
Key code
adjustedsurv(..., conf_int=TRUE, bootstrap=TRUE)

Reference / docs ↗

Discussion on this step (0)
  • No comments on this step yet — be the first.
4
Reporting

Summaries: RMST difference, survival at t

Reporting — turn the numbers into a figure or table a reader can act on.

What happens here

Collapse the curves to interpretable numbers: restricted mean survival time, or survival probability at a chosen horizon.

Formula
\mathrm{RMST}_a( au)=\int_0^{ au}\hat S_a(t)\,dt,\qquad \Delta=\mathrm{RMST}_1-\mathrm{RMST}_0
Reads from the input data Feeds into the final output
Key code
adjusted_rmst(adj, to=5)

Reference / docs ↗

Discussion on this step (0)
  • No comments on this step yet — be the first.
3

Output · what you get 2 figures

Confounder-adjusted survival curves for treated (1) vs control (0), with 95% confidence bands — the adjusted gap is the causal effect on survival, not a raw Kaplan-Meier.
Fig 1Confounder-adjusted survival curves for treated (1) vs control (0), with 95% confidence bands — the adjusted gap is the causal effect on survival, not a raw Kaplan-Meier.
A scenario where, once confounders are accounted for, the two groups' adjusted curves nearly coincide — no survival benefit after de-confounding.
Fig 2A scenario where, once confounders are accounted for, the two groups' adjusted curves nearly coincide — no survival benefit after de-confounding.

Figures reproduced from adjustedCurves — Robin Denz — unofficial community showcase; all credit to the original authors.

⚠️ Unofficial community showcase of adjustedcurves. Not affiliated with the authors; all credit to them.

Compare survival between treatment groups after removing confounding — via IPTW, the g-formula or AIPW — instead of a raw Kaplan-Meier that quietly bakes in selection.

Discussion (2)

  • 2

    Raw Kaplan-Meier between treatment groups in an observational study is the mistake I see most. IPTW-adjusted curves should be the default.

  • 0

    Reporting the RMST difference alongside the curves is the part clinicians actually act on. Good to see it as its own step.

    1

    Yes — survival-at-t plus RMST difference communicates far better than a hazard ratio nobody can interpret.