← Methods repository
CONCEPTINTERMEDIATEPYTHON · R · SAS5 citations

Landmark Analysis

A survival-analysis strategy that fixes a pre-specified landmark time, restricts to subjects event-free and under observation at that time, classifies exposure using only information available up to the landmark, and resets the time origin to the landmark for outcome follow-up, thereby removing guarantee-time (immortal time) bias from post-baseline exposure or response classifications.

Causal Inference Methodlandmark-analysissurvival-analysistime-to-eventimmortal-time-biasguarantee-time-biasconditional-landmarkcompeting-risksoncology-rwe
On this page
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

When researchers want to compare cancer patients who responded to treatment versus those who did not, they face a hidden trap: responders had to survive long enough to be classified as responders, giving them a head-start advantage that has nothing to do with the treatment. A fixed-point analysis fixes this by choosing a specific calendar day — say, day 90 after diagnosis — and asking only: who was still alive and event-free on that day, and did they respond before it? Everyone who died or had their outcome before day 90 is set aside, the groups are locked in based only on what happened before day 90, and survival tracking begins fresh from day 90 onward. This gives each group a fair start and measures how long patients lived *after* the classification moment, not from a zero point that secretly favors one group.

When to use it
Whenever exposure or response is defined after follow-up begins and a transparent, easily audited correction is required.
When the question is conditional on reaching a clinically meaningful time point, or as a transparent sensitivity analysis on a time-dependent primary model.
A one-time exposure/response classification at a fixed point, not a sustained-strategy estimand.
Watch out for
Discards all pre-landmark person-time and every subject who fails before the landmark, reducing efficiency and shifting the estimand to a conditional one.
Less efficient (throws away pre-landmark person-time and early failures); estimate depends on the arbitrary landmark choice; a single landmark misrepresents repeatedly changing exposure.
Cannot represent sustained, dynamic, or grace-period strategies; does not handle time-varying confounding affected by prior treatment.

Landmark analysis

answers a conditional question in time-to-event data: among subjects who are still alive, event-free, and under observation at a fixed clock time (the landmark), what is the outcome hazard contrasted by an exposure or response status that is fully determined by that landmark?

The defining mechanic is a deliberate realignment of the time axis. You

  1. choose a landmark time `L` from clinical knowledge of when the classifying event is observable (e.g., 90 days after a cancer diagnosis, 30 days after an MI hospitalization),
  2. discard everyone who has the outcome, dies, or is censored before `L`,
  3. freeze exposure status using only data accrued in `[index, L]`, and
  4. start the outcome clock at `L` (`follow_up = event_date - L`).

A standard Cox model, Kaplan-Meier curve, or Fine-Gray competing-risks model is then fit on the landmark-conditional cohort.

Core estimand distinction

Landmark estimates the exposure-outcome contrast conditional on being event-free and observable at the landmark, with exposure as known by the landmark — it is not a marginal effect from time zero, and it is not the same estimand as the alternatives it is usually compared with.

A time-dependent (extended) Cox model (see standard-cox-time-dependent) uses all person-time and lets exposure accrue as a time-varying covariate, so pre-landmark person-time is retained and the at-risk set is never truncated; it estimates an instantaneous-hazard contrast across the whole follow-up. Clone-censor-weight / g-methods (see marginal-structural-models-g-methods) assign every subject to treatment strategies at baseline, censor at the moment they deviate, and weight for the resulting informative censoring, targeting a strategy contrast under sustained regimens.

Landmark is the simplest of the three but answers the narrowest question: it conditions on survival to `L` and therefore changes both the population (landmark survivors) and the time origin. The competing-risks estimand must also be pre-specified — a cause-specific hazard (PROC PHREG / coxph) answers an etiologic question, while a subdistribution hazard / cumulative incidence (Fine-Gray) answers an absolute-risk question; the two diverge whenever competing mortality differs by exposure (see competing-risks-cause-specific-fine-gray-rwe).

Pros, cons, and trade-offs

  • vs naive "ever exposed / ever responder" from time zero: the naive contrast gives exposed/responder subjects credit for the immortal time they had to survive in order to become exposed — pure guarantee-time bias that manufactures an apparent benefit. Landmark removes it by construction (no one can be classified before they have survived to `L`). Prefer landmark whenever exposure or response is defined after follow-up begins and a simple, transparent fix is wanted.
  • vs time-dependent (extended) Cox: landmark is trivial to specify, communicate, and audit, and it sidesteps the proportional-hazards-of-a-time-varying-covariate assumption. Cost: it throws away all pre-landmark person-time and every subject who fails before `L`, so it is less efficient and the estimate is sensitive to the (arbitrary) choice of `L`. Prefer time-dependent Cox when efficiency matters, when exposure changes repeatedly, or when no single clinically meaningful landmark exists; prefer landmark when the scientific question is genuinely conditional ("among patients alive and responding at 90 days...") or as a transparent sensitivity check on a time-dependent model.
  • vs clone-censor-weight / g-methods: landmark cannot represent dynamic, sustained, or grace-period strategies and does not handle treatment-confounder feedback. Prefer g-methods for those estimands; prefer landmark for a one-time classification at a fixed point.

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

  • Most events occur before a defensible landmark. If the outcome is fast (e.g., 30-day mortality) and `L` is large, you discard most events and the surviving cohort is a thin, selected slice — the estimate may be precise nonsense.
  • Strong selection on survival-to-landmark. Conditioning on event-free survival to `L` can open a collider path: if an unmeasured factor causes both early events and the exposure, the landmark cohort is differentially depleted by exposure and the conditional contrast is confounded even if time zero was clean. This is dangerous precisely because landmark looks like it has solved the bias problem.
  • Procedure- or response-anchored time zero without an eligibility anchor. If you set the index (not just the landmark) at the procedure/response itself, you re-import immortal time through the back door — pair landmark with an eligibility-based time zero (diagnosis, hospitalization).
  • Repeatedly changing exposure. A single landmark freezes a status that genuinely varies; the frozen classification misattributes later person-time. Use a time-dependent or sequential/dynamic landmark approach instead.
  • Data-driven landmark selection to maximize a hazard ratio — this is `p`-hacking with a survival curve.

Data-source operational depth

  • Claims (FFS vs MA): the landmark denominator ("event-free and observable at `L`") is only valid where claims are complete. Medicare Advantage and capitated/bundled person-time drop fee-for-service claims, so a subject can look event-free at `L` simply because their event was never billed to the FFS system — misclassifying the at-risk set. Require continuous A/B (and D if exposure is a drug) FFS enrollment from index through `L` and exclude MA-only person-time. Exposure-by-landmark uses pharmacy (`fill_date`, `days_supply`) or procedure codes accrued in `[index, L]`; sample fills, 90-day mail order, and free samples distort `days_supply` and the inferred initiation date. Differential competing-risk death by exposure is a specific trap in elderly claims: if the sicker arm dies before `L`, the landmark cohort is selectively healthier in that arm — run a Fine-Gray / CIF check, not just cause-specific Cox.
  • EHR: response and biomarker capture cluster at clinic visits, so the true classifying event may sit just on either side of `L`. Either snap the landmark to the visit grid or use last-observation-carried-forward and document it; do not pretend daily resolution you do not have. Loss-to-system before `L` (patient leaves the network) is informative censoring of the landmark denominator, not random.
  • Registry: event and treatment timing are high quality, but response/outcome adjudication lags — choose `L` after the adjudication cutoff so you are not classifying on an artificially undercounted event set. Registries typically lack full pharmacy exposure; link to claims to confirm initiation dates within `[index, L]`.
  • Linked claims-EHR-registry: the ideal substrate (EHR/registry severity + claims completeness + a death index to firm up the competing-risk and at-risk sets), but linkage selects the linkable subset and creates order/fill/service date discrepancies that must be reconciled before `index` and `L` are assigned.

Worked claims example

Question: does early statin initiation after acute MI reduce 1-year recurrent MI, and is the naive "ever-statin" estimate inflated by immortal time?

Cohort: adults with an index AMI hospitalization (`index_date` = discharge), ≥365 days of continuous FFS A/B/D enrollment before index (so washout and baseline are observed), and FFS-observable person-time through the landmark.

Landmark `L` = 90 days post-discharge. Exposure is classified using only fills in `[index_date, index_date + 90]`: a subject is an early initiator if any statin `fill_date` falls in that window (confirm `days_supply` ≥ 30 to exclude one-off samples).

Apply the landmark restriction

drop anyone with the outcome (recurrent MI), death, or disenrollment on or before day 90 — they cannot contribute to a 90-day-conditional contrast. Reset the clock: outcome follow-up time = `event_date - (index_date + 90)`, starting at zero on day 90, censoring at recurrent MI, death (competing risk), disenrollment, or 365 days post index.

Fit a cause-specific Cox (early vs late/non-initiator) for the etiologic HR and a Fine-Gray model for the cumulative-incidence contrast, because post-MI mortality is a strong competing risk that differs by statin use. Then show the bias: re-run the naive analysis that counts statin status as "ever in the year" from time zero (day 0) and contrast the hazard ratio — the naive HR is biased toward benefit because early initiators had to survive ~90 days to be classified.

Finally, repeat the landmark fit at `L` = 30, 60, 180 days as the pre-specified sensitivity grid and report all four, because the conditional population shifts with `L`.

Interpreting the output

A 6-month (180-day) landmark analysis of treatment responders vs non-responders returns: conditional overall survival at 12 months post-landmark = 74% (responders) vs 52% (non-responders), estimated among patients event-free at the landmark.

Formal interpretation. At the landmark time L = 180 days, the cohort is restricted to patients who have not yet experienced the outcome; time is reset to zero from that landmark, and survival is estimated from L onward. The 74% vs 52% comparison is a conditional estimate describing survival from month 6 to month 12 among the subset who reached month 6 event-free. Responder status is classified at or before L, so exposure is time-fixed within the landmark-defined subcohort.

This eliminates the immortal-time advantage that responders would otherwise inherit in a time-zero-anchored analysis — but the estimate is conditional on surviving to L and is therefore not marginal from treatment initiation.

Practical interpretation. Landmark analysis answers: "For patients who made it to 6 months without an event, does responding to therapy predict better outcomes thereafter?" This conditional framing is appropriate for prognostic labeling discussions and post-hoc responder analyses, but must be distinguished from the intention-to-treat estimate of overall survival from the start of treatment. Report the N at landmark, the 95% CI for each arm, and sensitivity analyses at pre-specified alternative landmark times.

Decision diagram

flowchart TD
  Idx[Index event = time zero<br/>e.g. AMI discharge / diagnosis] --> Win[Classification window index..L<br/>observe exposure or response]
  Win --> Chk{Event-free AND<br/>observable at landmark L?}
  Chk -- No: outcome/death/disenroll before L --> Drop[Excluded from landmark cohort<br/>by design - removes immortal time]
  Chk -- Yes --> Cls[Freeze exposure from index..L only<br/>early-exposed vs not]
  Cls --> Reset[Reset clock: follow_up = event_date - L<br/>new time origin = landmark]
  Reset --> Fit[Cause-specific Cox / KM / Fine-Gray<br/>on landmark-conditional cohort]
  Fit --> Sens[Sensitivity: repeat at L = 30/60/90/180<br/>report every landmark]
Landmark analysis mechanics. Exposure is classified only within the pre-landmark window, subjects failing before the landmark are excluded by design (removing guarantee-time bias), the time origin is reset to the landmark, and the estimand is conditional on landmark survival.
gantt
  title One subject - why landmark removes immortal time (landmark L = 90d)
  dateFormat YYYY-MM-DD
  axisFormat %b
  section Naive (biased)
  Immortal time credited to exposed (day 0 to first fill) :crit, imm, 2024-01-01, 75d
  section Landmark
  Classification window index..L (observe exposure) :done, win, 2024-01-01, 90d
  Landmark = new time origin :milestone, lm, 2024-03-31, 0d
  Outcome follow-up starts at L :active, fu, 2024-03-31, 275d
For a single subject, the naive analysis credits the pre-exposure interval (index to first fill) as exposed person-time (immortal time). Landmark instead uses index..L only to classify and starts outcome follow-up at L, so no immortal person-time is attributed to either arm.

Worked example

Scenario

Three lung cancer patients are diagnosed on January 1, 2024 (their index date). Researchers want to know whether patients whose tumors shrank by day 90 live longer afterward than those whose tumors did not. The landmark day is March 31, 2024 — exactly 90 days after index. Scan results and vital status are checked on that day. Only patients alive and recurrence-free on March 31 enter the comparison; their follow-up clock starts fresh on that date.

Dataset

One row per patient showing scan result (recorded during the classification window), vital status at the landmark, and the recurrence date used to compute follow-up time.

person_idindex_datescan_response_dateresponded_by_day90alive_at_landmarkrecurrence_dateincluded_in_analysis
10012024-01-012024-02-15YesYes2024-09-15Yes
10022024-01-01none by day 90NoYes2024-11-15Yes
10032024-01-01N/A — died before landmarkN/ANo (died 2024-03-10)N/ANo — EXCLUDED
FIG. 1 — DESIGN TIMELINE
Horizontal timeline from January 1 to November 15, 2024. A shaded classification band runs from January 1 to March 31. A vertical line marks the day-90 landmark on March 31. Patient 1001 has a response event on February 15 and a recurrence on September 15, with a follow-up bar from the landmark to that recurrence labeled 168 days. Patient 1002 has no response event and a recurrence on November 15, with a follow-up bar from the landmark labeled 229 days. Patient 1003 has a death marker on March 10, before the landmark, with a label indicating exclusion.
Timeline for three patients with a day-90 landmark. The shaded band (January 1 – March 31) is the classification window: scan results recorded here determine each patient's group. The vertical marker at March 31 is the landmark itself — follow-up for the two surviving patients begins here.

Steps

1Set the landmark day: index date January 1 plus 90 days = March 31, 2024.
2Check each patient's vital status and outcome status on March 31: patient 1001 is alive and recurrence-free — keep; patient 1002 is alive and recurrence-free — keep; patient 1003 died on March 10, which is before the landmark — exclude by design.
3Lock each remaining patient's group using only records from January 1 through March 31: patient 1001 had a scan showing tumor shrinkage on February 15 (day 46), so they are in the 'responded' group; patient 1002 had no qualifying response scan before March 31, so they are in the 'did not respond' group.
4Reset the follow-up clock to zero at March 31 for both included patients: patient 1001 has their recurrence on September 15, giving 168 days of follow-up (April = 30, May = 31, June = 30, July = 31, August = 31, September 1–15 = 15 days; total = 168); patient 1002 has their recurrence on November 15, giving 229 days of follow-up (add October = 31 and November 1–15 = 15 days to the 183 days through September 30; total = 229).
5Both patients have the outcome (recurrence), so neither is censored in this small example; in a real study, patients still event-free at the end of the observation window would be censored at that point.
6The contrast is now fair: both responder and non-responder entered the risk set on the same calendar day (March 31), and no one's pre-landmark survival is counted as post-landmark follow-up.

Result

Label

Responder (patient 1001): 168 days to recurrence from landmark. Non-responder (patient 1002): 229 days to recurrence from landmark. Patient 1003 excluded (died before landmark day 90). Analysis is conducted only on the 2 patients event-free at day 90, with follow-up measured from day 90 forward.

Value

168 days (responder) vs 229 days (non-responder) post-landmark follow-up; 1 patient excluded pre-landmark

Trade-offs

vs. Naive "ever exposed / ever responder" from time zero
Pros of this
Removes guarantee-time (immortal time) bias by construction — no subject can be classified as exposed before surviving to the landmark, so exposed person-time is not credited as immortal.
vs. Time dependent (extended) Cox model
Pros of this
Trivial to specify, communicate, and audit; avoids the proportional-hazards assumption on a time-varying covariate; answers a genuinely conditional clinical question ("among those event-free at the landmark...").
vs. Clone censor weight / marginal structural g methods
Pros of this
Far simpler; no weighting machinery, no treatment-confounder feedback model, fully interpretable from the cohort table.

Runnable example

Landmark analysis from a claims/EHR analytic table, with a multi-landmark sensitivity loop. Required input (one row per subject, already cleaned): df : person_id, index_date (datetime), expose_date (datetime, NaT if never exposed by landmark), event_date (datetime), event (1=outcome, 2=competing death, 0=censored at...

requires: pandas · lifelines
import pandas as pd
from lifelines import CoxPHFitter

def landmark_cox(df: pd.DataFrame, landmark_days: int) -> CoxPHFitter:
    L = df["index_date"] + pd.Timedelta(days=landmark_days)

    # (1) Keep only subjects EVENT-FREE and OBSERVABLE at the landmark.
    #     Anyone with the outcome/death/disenrollment on or before L is excluded by design.
    at_risk = (df["event_date"] > L) & (df["obs_end"] >= L)
    lm = df.loc[at_risk].copy()
    lm["L"] = L[at_risk]

    # (2) Freeze exposure using ONLY information available by the landmark.
    lm["early_exposed"] = (lm["expose_date"].notna() & (lm["expose_date"] <= lm["L"])).astype(int)

    # (3) Reset the time origin to the landmark; follow-up starts at 0 on day L.
    lm["fu_time"] = (lm["event_date"].clip(upper=lm["obs_end"]) - lm["L"]).dt.days
    lm["cs_event"] = (lm["event"] == 1).astype(int)   # cause-specific: competing death treated as censored
    lm = lm[lm["fu_time"] > 0]

    # (4) Cause-specific Cox on the landmark-conditional cohort.
    model = CoxPHFitter()
    model.fit(lm[["fu_time", "cs_event", "early_exposed"]],
              duration_col="fu_time", event_col="cs_event")
    return model

# Pre-specified landmark sensitivity grid (report all; never pick the landmark from the results).
for L_days in (30, 60, 90, 180):
    m = landmark_cox(df, L_days)
    hr = m.hazard_ratios_["early_exposed"]
    print(f"landmark={L_days}d  n={m.event_observed.shape[0]}  HR={hr:.2f}")

Citations

FOUNDATIONAL / METHODS
  1. [1]Dafni U. Landmark analysis at the 25-year landmark point. Circulation: Cardiovascular Quality and Outcomes. 2011;4(3):363-371.
  2. [2]Anderson JR, Cain KC, Gelber RD. Analysis of survival by tumor response. Journal of Clinical Oncology. 1983;1(11):710-719.
  3. [3]Suissa S. Immortal time bias in pharmacoepidemiology. American Journal of Epidemiology. 2008;167(4):492-499.
  4. [4]Cho IS, Chae YR, Kim JH, et al. Statistical methods for elimination of guarantee-time bias in cohort studies: a simulation study. BMC Medical Research Methodology. 2017;17(1):126.
APPLIED EXAMPLES
  1. [5]Giobbie-Hurder A, Gelber RD, Regan MM. Challenges of guarantee-time bias. Journal of Clinical Oncology. 2013;31(23):2963-2969.