← Methods repository
concept

Restricted Mean Survival Time (RMST)

The expected event-free survival time accumulated up to a pre-specified horizon tau, equal to the area under the survival curve from 0 to tau, summarized between groups as an RMST difference (months gained) or RMST ratio without assuming proportional hazards.

Inferential_Statisticsrmstrestricted-mean-survival-timesurvival-analysisnon-proportional-hazardstime-scaleoncology-rwehta-relevantclaims
Methods reference only. Use primary source citations and local policy before applying this in a study protocol, regulatory submission, payer dossier, or clinical decision.

In plain language

Restricted Mean Survival Time (RMST) measures how many days, on average, patients in a study group stayed free of a bad health event — such as a heart attack or hospitalization — during a fixed window of time. Instead of asking 'are patients in one group dying faster?', it asks 'how many more event-free days did patients on Drug A accumulate compared to Drug B before the window closed?' You pick the window length (called tau, the Greek letter τ) before the study starts — for example, 36 months — and RMST is simply the average event-free time each group built up inside that window. The difference between the two groups' RMSTs tells you, in plain days or months, how much extra event-free time the better treatment delivered — a number that patients, doctors, and payers can all picture immediately.

Restricted mean survival time (RMST)

at a horizon tau is the area under the survival curve S(t) from time 0 to tau: RMST(tau) = integral_0^tau S(t) dt. Estimated non-parametrically, it is the area under the Kaplan-Meier step function, computed as the sum of rectangles S(t_k) * (t_{k+1} - t_k) over event/censoring times up to tau. It has the units of the time axis (months, years) and a direct interpretation: the average amount of event-free time a patient in this group accrues during the first tau units of follow-up. The between-group RMST difference (RMST_A - RMST_B) is the average number of additional event-free months gained, and the RMST ratio is its multiplicative analogue. Both are well-defined whether or not the hazards are proportional, which is the central reason RMST has displaced the hazard ratio as the primary or co-primary summary in many non-proportional-hazards settings.

Core estimand distinction

RMST is a summary measure on the time scale, not a model and not, by itself, a causal estimand. The hazard ratio from Cox is a single multiplicative contrast of instantaneous risk that is only interpretable as one number when proportional hazards (PH) holds; under crossing or delayed-separation curves the population HR is a follow-up-weighted average of changing hazard ratios with no fixed clinical meaning, and it can be driven by sparse late events. RMST(tau) instead integrates the entire curve up to tau, so it is robust to the shape of the hazard and to what happens after tau. Two further distinctions matter in RWE. (1) Unadjusted vs covariate-adjusted RMST: the KM-area RMST difference estimates a marginal (population-average) contrast under independent censoring; to target an adjusted ATE/ATT you must use pseudo-observation regression, IPTW-weighted KM, or g-computation, and the adjusted RMST difference is then a marginal causal contrast only if confounding is fully controlled. (2) Event definition under competing risks: when death competes with the event of interest, "RMST" can mean restricted mean event-free time (treating the competing event as censoring, which is usually wrong) or restricted mean time-in-state computed from the cumulative incidence function (Aalen-Johansen), i.e. expected life-years lost. Pre-specify which one in the estimand; they answer different questions.

Pros, cons, and trade-offs

- vs Cox proportional-hazards / hazard ratio (cox-ph-regression): RMST needs no PH assumption, is reported in interpretable time units that payers and patients understand ("3.1 months gained"), is robust to heavy administrative censoring and to sparse, influential late events, and gives a single honest number when the HR does not. Cost: RMST requires choosing tau (a substantive, not statistical, decision), is modestly less efficient than Cox when PH genuinely holds, and is less familiar to some clinical audiences. Prefer RMST whenever PH is violated, doubtful, or untestable, or when an absolute time horizon is the decision-relevant quantity. Prefer the HR when PH is credible and a relative instantaneous-risk contrast is the target. - vs survival extrapolation for lifetime QALYs (survival-extrapolation-hta-rwe): RMST stays inside the observed follow-up window (t <= tau) and therefore makes no parametric tail assumptions, which is its honesty advantage. Cost: it deliberately does not answer the lifetime-horizon question a cost-utility model needs; restricting to tau truncates any benefit accruing after tau. Prefer RMST for within-trial / within-data effect summaries and HTA "minimum months gained" claims; prefer extrapolation when the decision genuinely needs lifetime mean survival. - vs g-methods for time-varying treatment (g-estimation-structural-nested-models, clone-censor-weight-per-protocol): RMST is a marginal summary up to tau and is simple to specify and communicate. Cost: it does not by itself handle time-varying confounding, treatment switching, or dynamic per-protocol strategies. Prefer plain RMST for an initiation (ITT-like) contrast; combine RMST with clone-censor-weight or MSMs as the summary measure when the estimand is a sustained or per-protocol strategy.

When to use

Crossing or delayed-separation survival curves (classic in immuno-oncology, where the HR averages a null early period with a later benefit); heavy administrative censoring before the median is reached in either arm (common in claims with short, calendar-bounded enrollment); HTA, payer, or patient-facing questions that value absolute event-free time within a fixed policy horizon (1-, 3-, or 5-year RMST for value frameworks and budget-impact narratives); and any setting where PH is clearly violated or cannot be tested because late events are sparse. Reporting RMST at several pre-specified horizons (e.g. 1, 3, 5 years) is good practice when the benefit profile changes over time.

When NOT to use — and when it is actively misleading or dangerous

- tau chosen after looking at the data, or beyond reliable follow-up. Setting tau past the last event in one arm forces extrapolation through a flat KM tail and silently fabricates "gained" time; choosing tau to maximize the difference is p-hacking on the time scale. tau must be fixed a priori on clinical or policy grounds, and the minimum of the two arms' largest observed event/censoring times should bound it. Always report the number still at risk at tau. - Competing risks handled as independent censoring. Censoring deaths to compute "event-free RMST" overstates event-free time, and the bias is differential when mortality differs by arm - exactly the elderly, multimorbid claims populations where this method is most tempting. Use the CIF/Aalen-Johansen restricted-mean-time-in-state (life-years lost) instead. - Informative censoring from disenrollment or switching. Unadjusted KM-area RMST assumes censoring is independent of prognosis. Differential loss to follow-up (Medicare Advantage churn, plan switching, differential switching at progression) biases it; use inverse-probability-of-censoring weighting or restrict tau before typical switch time. - Confounded observational contrast read as causal. RMST removes the PH assumption, not confounding by indication. An unadjusted RMST difference between two drugs in claims is descriptive; adjustment (pseudo-observation regression, IPTW, g-computation) is still mandatory. - PH genuinely holds and a single tau is reported. Then RMST throws away efficiency relative to the HR with no interpretive gain; report the HR (and optionally RMST as a co-primary for communication).

Data-source operational depth

- Claims (FFS): The time axis is days from index. Event = first qualifying outcome claim (e.g. inpatient HF diagnosis in the primary position); censor at the earliest of disenrollment, death, end of continuous enrollment, and study end. tau is set to the reimbursement/value horizon (commonly 24 or 36 months), never to the data. Failure modes: Medicare Advantage person-time lacks FFS encounter claims, so events go uncaptured and patients appear event-free until they disenroll - restrict to A/B (and D where exposure is a drug) FFS person-time and treat MA enrollment as censoring, not follow-up. Differential competing risk: in elderly claims, non-cancer death competes with the event and is more frequent in the sicker arm; event-free RMST must use the CIF, not censored KM. Immortal time: if the index requires a post-initiation procedure, follow-up must start at the procedure date or the early flat survival inflates RMST in that arm. Coarse timing: days_supply and claim adjudication lags mean event dates are interval-censored at the day level; integrate the KM on the finest available unit (days) and avoid month-rounding. - EHR: Event dates can be sharper (progression notes, lab thresholds, structured problem lists) but capture is visit-driven, so a patient who leaves the system is differentially and informatively censored. Use last-contact or the end of database coverage as the censor and consider inverse-probability-of-observation weighting if visit intensity differs by arm; otherwise the arm with denser surveillance accrues apparent events earlier and its RMST is biased downward. - Registry: Usually the longest, cleanest, adjudicated follow-up with explicit visit schedules - the best substrate for RMST and for validating claims-based RMST. Still pre-specify tau before plotting the curves, and confirm vital-status ascertainment is complete so administrative censoring is non-informative. - Linked claims-EHR-vital records: The ideal substrate (EHR severity + claims completeness + reliable mortality for competing-risk RMST), but linkage selects the linkable subset and order/fill/service date discrepancies must be reconciled before the time axis is fixed.

Worked claims example

Question: 36-month restricted mean event-free time to first heart-failure hospitalization, second-generation sulfonylurea (SU) vs DPP-4 inhibitor, incident users with type 2 diabetes in a Medicare FFS + commercial database; tau = 1095 days, fixed before any analysis on the value-framework horizon. (1) Cohort: age >= 18, >= 2 diabetes diagnoses, 365 days continuous A/B/D FFS or commercial medical+pharmacy enrollment before index, no SU or DPP-4 fill in that washout (incident users), arm assigned from the NDC dispensed on the first qualifying fill (index_date = fill_date). (2) Event = first inpatient claim with HF in the primary diagnosis position after index_date; event time = days from index. (3) Censoring at the earliest of disenrollment, switch to MA (FFS claims stop), death from the linked death index, and study end - and because non-cardiovascular death is a competing risk that is more common in the older SU initiators, the primary analysis uses the Aalen-Johansen CIF restricted mean time-in-state, not censored KM. (4) Suppose the cause-specific KM yields RMST_DPP4 = 33.4 months and RMST_SU = 31.7 months over 36 months, with 41% of DPP-4 and 38% of SU initiators still at risk at tau: unadjusted RMST difference = 1.7 months (95% CI by the closed-form Uno variance or 2,000 bootstrap resamples of patients). (5) Because the arms differ at baseline, the reported estimate is the IPTW-weighted (or pseudo-observation-regression-adjusted) RMST difference on a high-dimensional propensity score built only from the 365-day baseline window. (6) Sensitivity: re-run at tau = 24 and 48 months, swap the competing-risk handling, vary the grace period defining switching, and run a negative-control outcome - if the adjusted RMST difference is stable, the "average ~1.7 additional HF-hospitalization-free months over 3 years on DPP-4" claim is defensible for the payer narrative.

Interpreting the output

An RMST analysis of DPP-4 inhibitor vs sulfonylurea at a 24-month horizon returns: RMST difference = 1.8 months (≈55 days; 95% CI 0.3–3.3 months) in favor of DPP-4.

Formal interpretation. The restricted mean survival time is the area under the Kaplan-Meier curve from time zero to the pre-specified horizon τ = 24 months; it equals the expected event-free time a patient accumulates before month 24 under each treatment arm. The estimated RMST difference of 1.8 months means that, on average, patients initiated on DPP-4 therapy spend approximately 1.8 more months free of their first heart-failure hospitalization within a 24-month window compared with sulfonylurea initiators, after IPTW adjustment. The horizon τ must be fixed before analysis; re-running at different τ values is a pre-specified sensitivity analysis, not selective reporting.

Practical interpretation. Unlike the hazard ratio, the RMST difference is an absolute, time-anchored quantity expressed in the same units as follow-up — months or days — making it directly meaningful to patients and payers. It does not require the proportional-hazards assumption and remains valid even when survival curves cross. The 1.8-month gain translates to roughly 55 additional event-free days per patient on average, which a value narrative can frame against the cost difference between the two drug classes at the chosen time horizon.

Worked example

Scenario

A researcher uses Medicare insurance claims to compare two diabetes drugs — a DPP-4 inhibitor versus a sulfonylurea (SU) — on time to first heart-failure hospitalization. She fixes tau = 1095 days (36 months) before looking at any data, because 36 months is the payer's standard budget-planning horizon. She identifies four representative patients — two per drug arm — and tracks each one from their first fill (day 0) until either their hospitalization or the end of follow-up, whichever comes first. She wants to know: on average, how many event-free days did each arm accumulate before day 1095?

Dataset

One analytic row per patient as an analyst would see it after building the cohort. fu_days = days from first fill to event or censoring; event = 1 if hospitalized, 0 if censored (left insurance or reached day 1095 without the event).

person_idarmindex_datefu_daysevent
3001DPP-42020-01-151095
3002DPP-42020-03-028201
3003SU2020-01-201095
3004SU2020-02-104801

Steps

  • Each patient's contribution to RMST is the number of event-free days they add to their arm's running total, capped at tau (1095 days).

  • Patient 3001 (DPP-4): reached day 1095 without a hospitalization — contributes all 1095 event-free days.

  • Patient 3002 (DPP-4): was hospitalized on day 820 — contributes 820 event-free days (the days before the event count; the event day itself signals the end).

  • Patient 3003 (SU): also reached day 1095 without a hospitalization — contributes 1095 event-free days.

  • Patient 3004 (SU): was hospitalized on day 480 — contributes 480 event-free days.

  • DPP-4 arm average: (1095 + 820) / 2 = 957.5 event-free days per patient.

  • SU arm average: (1095 + 480) / 2 = 787.5 event-free days per patient.

  • RMST difference: 957.5 − 787.5 = 170 event-free days — the average extra time without hospitalization gained on the DPP-4 arm over this tiny sample.

  • In the full study (source YAML), the RMST difference across thousands of patients narrows to about 52 days (33.4 months vs 31.7 months), which is why real RMST estimates need large samples — the two-patient average above just illustrates the arithmetic, not the real-world magnitude.

Result

  • Label

    RMST — DPP-4 arm (full study, 36-month window)

    Value

    1017 days (33.4 months)

  • Label

    RMST — Sulfonylurea arm (full study, 36-month window)

    Value

    965 days (31.7 months)

  • Label

    RMST difference (DPP-4 minus SU)

    Value

    52 days (~1.7 months) of additional event-free time on average

Timeline Spec

Title

RMST over a 1095-day (36-month) window — two patients per arm, heart-failure hospitalization endpoint

Caption

Each patient's bar runs from day 0 (first fill) until hospitalization (filled triangle) or the end of the window (open circle). RMST for each arm is the average length of the event-free bars. The DPP-4 arm averages 957.5 days of event-free time in this two-patient slice; the SU arm averages 787.5 days.

Alt Text

Horizontal timeline from day 0 to day 1095 showing four patient bars. DPP-4 patients (top two): Patient 3001's bar runs the full 1095 days ending in an open circle; Patient 3002's bar ends at day 820 with a filled triangle (hospitalization). SU patients (bottom two): Patient 3003's bar runs the full 1095 days; Patient 3004's bar ends at day 480 with a filled triangle. The average bar length for the DPP-4 arm is visibly longer than for the SU arm.

Window
End Day

1095

Label

Tau = 1095 days (36-month policy horizon, fixed before analysis)

Arms
  • Label

    DPP-4 inhibitor arm

    Patients
    • Person Id

      3001

      End Day

      1095

      Marker

      censor

      Marker Label

      Still event-free at tau

    • Person Id

      3002

      End Day

      820

      Marker

      event

      Marker Label

      Hospitalized day 820

    Rmst Days

    957.5

  • Label

    Sulfonylurea (SU) arm

    Patients
    • Person Id

      3003

      End Day

      1095

      Marker

      censor

      Marker Label

      Still event-free at tau

    • Person Id

      3004

      End Day

      480

      Marker

      event

      Marker Label

      Hospitalized day 480

    Rmst Days

    787.5

Spans
  • Kind

    followup

    Arm

    DPP-4 inhibitor arm

    Person Id

    3001

    End Day

    1095

    Label

    1095 event-free days

  • Kind

    followup

    Arm

    DPP-4 inhibitor arm

    Person Id

    3002

    End Day

    820

    Label

    820 event-free days

  • Kind

    followup

    Arm

    Sulfonylurea (SU) arm

    Person Id

    3003

    End Day

    1095

    Label

    1095 event-free days

  • Kind

    followup

    Arm

    Sulfonylurea (SU) arm

    Person Id

    3004

    End Day

    480

    Label

    480 event-free days

Result
  • Label

    DPP-4 arm RMST (2-patient slice)

    Value

    957.5

  • Label

    SU arm RMST (2-patient slice)

    Value

    787.5

  • Label

    RMST difference (DPP-4 minus SU, 2-patient slice)

    Value

    170.0

  • Label

    Full-study RMST difference (~1.7 months, consistent with source data)

    Value

    52

Runnable example

python implementation

Non-parametric RMST(tau), bootstrap CI for the RMST difference, and a covariate-adjusted RMST regression via jackknife pseudo-observations. Required input: one analytic row per patient (already constructed upstream) with person_id : patient id arm : 1 =...

import numpy as np
import pandas as pd
import statsmodels.api as sm
import statsmodels.formula.api as smf
from lifelines import KaplanMeierFitter
from lifelines.utils import restricted_mean_survival_time

TAU = 1095  # days = 36 months, fixed a priori on the value horizon

def rmst_by_arm(df: pd.DataFrame, tau: int = TAU) -> dict:
    """KM-area RMST(tau) within each arm; tau must be <= each arm's last observed time."""
    out = {}
    for a, g in df.groupby("arm"):
        kmf = KaplanMeierFitter().fit(g["fu_time"], g["event"])
        out[a] = restricted_mean_survival_time(kmf, t=tau)
    return out

def rmst_diff_bootstrap(df: pd.DataFrame, tau: int = TAU, n_boot: int = 2000, seed: int = 1) -> dict:
    """Unadjusted RMST difference (arm 1 - arm 0) with a patient-level bootstrap percentile CI."""
    rng = np.random.default_rng(seed)
    point = rmst_by_arm(df, tau)
    diff = point[1] - point[0]
    ids = df["person_id"].to_numpy()
    boots = np.empty(n_boot)
    for b in range(n_boot):
        samp = df.iloc[rng.integers(0, len(df), len(df))]   # resample patients with replacement
        r = rmst_by_arm(samp, tau)
        boots[b] = r.get(1, np.nan) - r.get(0, np.nan)
    lo, hi = np.nanpercentile(boots, [2.5, 97.5])
    return {"rmst_arm1": point[1], "rmst_arm0": point[0], "rmst_diff": diff, "ci95": (lo, hi)}

def km_area_rmst(times: np.ndarray, events: np.ndarray, tau: int) -> float:
    """RMST(tau) = area under the Kaplan-Meier curve from 0 to tau for one sample."""
    kmf = KaplanMeierFitter().fit(times, events)
    return restricted_mean_survival_time(kmf, t=tau)

def rmst_pseudo_values(df: pd.DataFrame, tau: int = TAU) -> np.ndarray:
    """Correct leave-one-out jackknife pseudo-observations of RMST(tau).

    For each subject i: pseudo_i = N*RMST_all - (N-1)*RMST_without_i, where each RMST is the
    KM-area to tau computed on the full sample and on the sample excluding subject i. This is the
    Andersen-Klein definition; a censored subject does NOT simply contribute its censoring time.
    """
    times  = df["fu_time"].to_numpy()
    events = df["event"].to_numpy()
    n = len(df)
    rmst_all = km_area_rmst(times, events, tau)
    keep = np.ones(n, dtype=bool)
    pseudo = np.empty(n)
    for i in range(n):
        keep[i] = False
        rmst_minus_i = km_area_rmst(times[keep], events[keep], tau)
        pseudo[i] = n * rmst_all - (n - 1) * rmst_minus_i
        keep[i] = True
    return pseudo

def adjusted_rmst_regression(df: pd.DataFrame, covars: list[str], tau: int = TAU):
    """Covariate-adjusted RMST difference via pseudo-observations + GEE (identity link).

    Pseudo-observations theta_i are regressed on arm + covariates; the 'arm' coefficient is the
    adjusted RMST difference. Use independence working correlation since rows are one-per-patient.
    """
    df = df.copy()
    df["pseudo"] = rmst_pseudo_values(df, tau)
    formula = "pseudo ~ arm + " + " + ".join(covars)
    gee = smf.gee(formula, groups=df["person_id"], data=df,
                  family=sm.families.Gaussian(), cov_struct=sm.cov_struct.Independence()).fit()
    return gee  # gee.params['arm'] is the adjusted RMST difference (days); gee.conf_int() for the CI
r implementation

Unadjusted RMST difference with the survRM2 package and covariate-adjusted RMST regression via pseudo-observations and GEE. Required input: one analytic row per patient with fu_time : follow-up time in DAYS from index to event/censoring event : 1 = event...

library(survRM2)
library(pseudo)
library(geepack)

tau <- 1095  # days = 36 months, fixed a priori

## 1) Unadjusted RMST in each arm + difference and ratio with closed-form (Uno) CIs.
fit <- rmst2(time = df$fu_time, status = df$event, arm = df$arm, tau = tau)
print(fit)                       # RMST per arm, RMST difference, RMST ratio, 95% CIs, p-values
rmst_diff <- fit$unadjusted.result["RMST (arm=1)-(arm=0)", "Est."]

## 2) Covariate-adjusted RMST difference via jackknife pseudo-observations + GEE (identity link).
##    pseudomean() returns the leave-one-out RMST pseudo-value for each subject at tmax = tau.
df$pseudo <- pseudomean(time = df$fu_time, event = df$event, tmax = tau)
df <- df[order(df$person_id), ]
gee_fit <- geeglm(pseudo ~ arm + age + sex + comorb_score,
                  id = person_id, data = df,
                  family = gaussian("identity"), corstr = "independence")
summary(gee_fit)                 # coefficient on 'arm' = adjusted RMST difference (days); use a log link for the ratio