AdvancedIndependently reviewed, not yet spot-checked by a human

Left truncation and delayed entry

Not everybody was under observation from day 0. How left truncation differs from left censoring, the two-time Surv(entry, exit, event) form, how far and in which direction survival is wrong without it, and why the whole bias lands on the people who entered late.

Left truncation and left censoring differ over one thing: the denominator

The two terms look alike and get used interchangeably, but they describe two different situations, and the fixes have nothing in common.

Left censoringLeft truncation
What you knowThe event has already happened; you only know its time was earlier than some pointBefore some point, this person could not have been seen to have the event at all
Typical settingThe first serology drawn is already positive; the infection date is unknownA registry whose enrolment date follows the diagnosis date; age as the time scale
What is missingA timeA stretch of observation
The fixA left- or interval-censored likelihood (Surv(time, time2, type = “interval2”))Put the entry time inside Surv() so the person is not in the denominator before it

Censoring and the risk set already draws the line between “in the data with incomplete time” and “not in the data at all”, and this page does not repeat it. What this page handles is the milder and far more common form of left truncation: people do get in, they just get in late — and the stretch they were late by is exactly the stretch during which they could not have been seen to have the event.

The worked example: a registry whose enrolment follows diagnosis

survival::myeloma holds Mayo Clinic patients with multiple myeloma: 3882 people, 2769 deaths observed, 1113 (28.7%) still alive when follow-up ended.

The point that matters is the time origin: day 0 in this dataset is diagnosis, not enrolment. For someone diagnosed at Mayo the two coincide. For someone diagnosed elsewhere and referred later, they do not, and the gap is recorded in the entry column.

nShare
entry of 0 — under observation from the day of diagnosis219456.5%
entry above 0 — under observation only later168843.5%

The median entry over the whole sample is 0, because more than half were enrolled on the spot, and that number tells you nothing. The distribution to look at is the one among the people who entered late: a median delay of 166 days, an interquartile range of 36 to 575 days, and one person who entered 5414 days after diagnosis.

The syntax: entry time goes in the first slot of Surv()

Two times inside Surv() say exactly what needs saying: when this person came under observation, and when they left it.

library(survival)
data(cancer, package = "survival")   # myeloma lives inside the `cancer` bundle
# note: data(myeloma, package = "survival") warns that no such dataset exists

# Ignoring delayed entry: everyone is treated as observed from day 0 (diagnosis)
fit_naive <- survfit(Surv(futime, death) ~ 1, data = myeloma)

# Correct: entry is the day this person actually joined the risk set
fit_corr  <- survfit(Surv(entry, futime, death) ~ 1, data = myeloma)

summary(fit_naive)$table[c("median", "0.95LCL", "0.95UCL")]
summary(fit_corr)$table[c("median", "0.95LCL", "0.95UCL")]

# Cox takes the identical change: put both times inside Surv()
coxph(Surv(entry, futime, death) ~ year, data = myeloma)

Verified with R 4.6.0 and survival 3.8.6. myeloma ships with the survival package; nothing else to install.

How far it is wrong, and in which direction

Same data, same people, same event definition. The only difference is one extra column inside Surv().

Two Kaplan-Meier curves on one panel. The x axis is days since diagnosis of myeloma, 0 to 3000, ticked every 500; the y axis is survival probability from 0 to 1. The blue curve is Surv(futime, death), which ignores delayed entry; the red curve is Surv(entry, futime, death), which handles it. Each carries a pair of dashed 95% confidence limits. The blue curve sits above the red one over the entire range and the two never cross. A brown dotted horizontal line marks survival 0.5, and two vertical dashed lines run up to it from the axis: the red one at 764 days, the blue one at 1004 days, with a double-headed arrow between them labelled 240 days apart. Two lines of small text above the plot give the sample size, how many entered late and their share, and survival at day 1000 under each formula. Below the plot is a two-row numbers-at-risk table on the same 500-day ticks: the row ignoring entry runs from 3882 down to 235, the row handling delayed entry from 2194 down to 219.
Two ways of writing one analysis of one dataset. The blue curve sits high not because it is optimistic but because its denominator contains 1688 people who, at that moment, could not have been seen to die.Plotting script figures/scripts/B3-08-left-truncation.R
FormulaMedian survival (95% CI)S(500 d)S(1000 d)S(2000 d)
Ignoring delayed entry
survfit(Surv(futime, death) ~ 1, data = myeloma)
1004 (952–1060)71.8%50.4%26.2%
Handling delayed entry
survfit(Surv(entry, futime, death) ~ 1, data = myeloma)
764 (728–811)63.2%41.0%19.2%
Difference (first minus second)240 days8.5 pp9.4 pp7.0 pp

The direction is not a quirk of this dataset — it is fixed: ignoring left truncation overestimates survival. Median survival rises from 764 days to 1004 days, a gain of 240 days, or 1.31 times the correct value. Survival at day 1000 rises from 41.0% to 50.4%, a gap of 9.4 percentage points.

In percentage points, of the three days tabulated above the gap is widest at day 1000 (9.4 pp), narrowing to 7.0 pp by day 2000. That is not the bias shrinking: by then both curves are close to the floor, so there is less room left to differ in.

The mechanism: identical numerator, different denominator

The cleanest way in is this: both formulas count exactly the same events.

Either way the count is 2769 deaths, not one added and not one removed. What changes is the size of the risk set that Kaplan-Meier divides by at each of those deaths. Inflate the denominator and every “fraction who died at this instant” is diluted; multiply the diluted terms together and the whole curve lifts.

Two stacked panels. Panel A, titled "who each formula thinks is under observation", has days since diagnosis from 0 to 3000 on the x axis and the number at risk from 0 to about 4000 on the y axis. The blue line, ignoring entry, starts at 3882 and falls monotonically to 235 by day 3000. The red line, handling delayed entry, starts at 2194 and, over the first couple of hundred days, first rises to a small peak before turning downward, ending at 219. That early rise is not a drawing error: it is what delayed entry looks like, with people joining after time zero. At day 0 a thick gold vertical segment marks the 1688-person gap between the two lines, with a note beside it that those people had not been referred yet. Panel B, titled as the gap in A counted at risk only by the naive formula, plots that difference: a gold curve over a filled area falling steeply from 1688 and then trailing off in a long tail, with solid dots at days 500, 1000 and 2000 and a legend giving the count and the share of the naive risk set at each. A line under the plot notes that these subjects had not been referred yet, so they could not have been seen to die.
The early rise in Panel A is the part worth stopping on: a risk set can grow, because referred patients keep arriving. Panel B is the difference between the two lines — the people the naive formula counts out of thin air.Plotting script figures/scripts/B3-08-left-truncation.R
DayDenominator, ignoring delayed entryDenominator, handling delayed entryNot yet enteredShare of the naive denominator
038822194168843.5%
5002335185947620.4%
10001469122824116.4%
150092980512413.3%
20006025346811.3%
2500387352359.0%
3000235219166.8%

The day-0 gap of 1688 is exactly the number of people with entry above 0 — not an approximation of it, the same set. The gap shrinks as referrals arrive, but at day 2000 the naive denominator still contains 11.3% who do not belong in it.

The bias is not spread evenly over the sample

Split the sample and run each half separately, and the most persuasive thing on this page appears.

SubgroupnEventsMedian, ignoring delayed entry (95% CI)Median, handling delayed entry (95% CI)Difference
entry == 0 (diagnosed at Mayo)21941889777 (729–823)777 (729–823)0 days
entry > 0 (referred later)16888801462 (1339–1581)795 (734–885)667 days

For the patients enrolled on the spot the two formulas give identical median survival (777 days), down to both ends of the confidence interval. That is no surprise: their entry is 0, so the two expressions are saying the same thing about them.

For the referred patients the two formulas differ by 667 days. The entire bias in the whole analysis lands on those 1688 people.

Two settings you will meet this term

One: a cohort with age as the time scale

In chronic disease epidemiology the time axis is often not “years of follow-up” but age — because for cardiovascular events, dementia or fracture, age is the dominant time scale, and using follow-up time while adjusting for age as a covariate demotes the most important variable in the problem.

Once the axis is age, everybody is left truncated: a participant enrolled at 62 was not observed from age 0 to 62, and the reason they could appear on your enrolment list at all is that they reached 62.

# Time scale = age in years. Age at enrolment is entry, age at the end of
# follow-up is exit. lung, already loaded above, stands in for the shape:
# age is age at enrolment and time is follow-up in days.
cohort <- data.frame(
  age_entry    = lung$age,
  futime_years = lung$time / 365.25,
  event        = as.integer(lung$status == 2),
  sex          = factor(lung$sex, levels = c(1, 2), labels = c("Male", "Female")),
  ecog         = lung$ph.ecog
)
cohort$age_exit <- cohort$age_entry + cohort$futime_years
coxph(Surv(age_entry, age_exit, event) ~ ecog + sex, data = cohort)

Two: registry and biobank studies, where enrolment follows disease onset

This is the first trap a student meets working with claims data or a hospital registry. Whenever the time origin and the date of entry into the database are not the same day, the stretch between them is left truncated:

  • A hospital cancer registry uses the date of diagnosis as the origin, but the patient was registered only on referral
  • A biobank uses the date of onset, but the specimen arrived, and entered the analysis, later
  • A database that begins in a given year, used to study patients diagnosed before that year — their origin predates the database, and appearing in it at all means they survived to the day it opened
  • The first prescription as the origin, in a database whose pharmacy records only start in some year

The code is the same every time: entry is days from the origin to database entry, exit is days from the origin to the event or the end of follow-up. The other traps in database studies and real-world data — claims exist for reimbursement, not research; what RECORD asks you to state — stack on top of this one rather than replacing it.

How this page relates to the others

  • Censoring, truncation and why the risk set is the denominator — back to censoring and the risk set. Its table of the three censoring types and the table at the top of this page are a matched pair.
  • How a KM curve is computed, and why a numbers-at-risk table is compulsory — see the Kaplan-Meier curve. The first figure here carries both risk rows precisely because those two rows are the entire reason the curves separate.
  • The Cox model — see the Cox proportional hazards model. Left truncation is the identical one-line change in coxph(), and every risk set in the partial likelihood is filtered by entry automatically.
  • Immortal time bias — a relative of delayed entry, but not the same thing, and worth keeping apart:
    • Delayed entry: during that stretch nobody was observing the person at all. The error is counting observation that never happened.
    • Immortal time bias: during that stretch you can see the person, but you grouped them by a status that was not yet known at the time (transplanted or not, responder or not), so guaranteed-alive time was credited to the wrong arm. The fixes point in opposite directions: the first takes time out of the risk set, the second keeps it in and moves it to the correct arm. B3-01 works through immortal time with the Stanford heart transplant data, and time-varying covariates and landmark analysis is where the fix lives.
  • Being eligible at all is itself a filter — see selection bias. Surv(entry, ...) repairs the denominator; it does not repair a population that has already been screened.

Common misuses

MisuseWhy it is wrong
Enrolment follows the origin, but the code says Surv(time, event)No error is raised and survival is overstated systematically; on this page by 240 days
Reading the overall median entry of 0 as “this does not affect us”The bias sits on the people who entered late, and a whole-sample quantile hides them
Using exit - entry as follow-up time instead of two timesThat changes the time origin rather than correcting anything; the clinical question changes with it
Age as the time scale, but only follow-up time in the codeEveryone is left truncated in that setting; it is the default there, not the exception
Treating left truncation as left censoring and reaching for an interval likelihoodLeft censoring is missing a time, left truncation is missing observation; the likelihoods differ
Claiming selection bias is handled because Surv(entry, exit, event) was usedOnly the denominator was repaired; who got the chance to be enrolled is still filtered
A Methods section that says only “Kaplan-Meier was used”The reader cannot tell whether delayed entry was handled, and this is the irreproducible line
Assuming the other assumptions hold once delayed entry is handledNon-informative censoring and proportional hazards are separate assumptions, each needing its own check

Reproducing every number on this page

/opt/homebrew/bin/Rscript figures/scripts/B3-08-left-truncation.R

Read the figure

The answer comes from the same statistical output that produced this page's figures, not from a number typed in beside them.

The same myeloma data give different median survival depending on whether delayed entry is handled. Which figure should be reported?

Show the answer and why

Correct answer: 764 days - putting each patient's entry time into the risk set

A referred patient had to survive until referral to appear in this dataset at all, and during that stretch they could not die by definition. Treating them as observed from diagnosis hands that impossible-to-die time to the survival curve, pushing the median from 764 days up to 1004. 728 is the lower confidence bound on the corrected median: it moves with the sample, so using it as a point estimate is not caution but a different quantity.

There are 3882 patients here. Which number tells you whether delayed entry is a problem worth handling?

Show the answer and why

Correct answer: 1688 have an entry time above zero, so observation of them begins after diagnosis

1688 patients entered late, close to half the cohort - and that share is what governs how much bias ignoring it introduces. 2194 entered at time zero and are unproblematic, but "the rest can be set aside" has it exactly backwards; 1113 is the censored count, and delayed entry is the opposite phenomenon: censoring is not seeing what came after, delayed entry is not seeing what came before. In the data this is a single entry column, and leaving it out of Surv() produces no complaint and a perfectly plausible answer.

Overall, ignoring versus handling delayed entry moves median survival by only 240 days, and someone concludes the problem is negligible. Which number best refutes that?

Show the answer and why

Correct answer: The late-entry group differs by 667 days, so the whole bias sits with them

Patients entering at time zero have no delayed-entry problem, so both methods give them the same median and the difference is 0; the entire bias comes from the late-entry group, where it is 667 days. The overall 240 is what remains after mixing the two together - half the cohort has no bias at all, so averaging them in is bound to look reassuring. "It barely moves overall" is therefore not a reason to ignore left truncation; the questions are how large the affected group is and how far it is off.

Watch next

Censoring and Truncation [Survival Analysis 2/8]
ENzedstatistics· 14 minWatch it after the first section here, before the numbers start. It keeps censoring and truncation apart as two separate things, which is the distinction the rest of this page is built on.

Sources and licences

This page is original writing

Report a content problem

The statistics on this site are written by AI and reviewed by AI; a human only spot-checks. What you can see may be what we cannot.

The more specific, the more fixable — e.g. which sentence disagrees with which textbook or paper.

Needed only if you want a reply; reports without it are still read.

Sent along with your report

These are attached automatically. You can drop any of them.