8  Survival curves

library(rtemis.draw)

Attaching package: 'rtemis.draw'
The following object is masked from 'package:graphics':

    Axis

draw_survfit() draws fitted survival curves; draw_survival() draws portable, precomputed curve records. Estimation belongs to the survival package or the producer of the records. Drawing does not refit a model.

8.1 Fit and draw

The survival package includes follow-up data from a lung cancer study. Here we estimate Kaplan–Meier curves by recorded sex, using its coding of 1 for male and 2 for female. In this dataset, status = 2 indicates death:

patients <- survival::lung
patients[["sex"]] <- factor(
  patients[["sex"]], levels = c(1, 2), labels = c("Male", "Female")
)
fit <- survival::survfit(
  survival::Surv(time, status) ~ sex, data = patients
)

draw_survfit(fit, xlab = "Days")

Steps give the estimated probability of survival beyond each time. The default bands retain the fit’s pointwise confidence intervals, and ticks mark censoring times. Hover a recorded point or censor tick for its estimate, bounds, risk count, and censor count. A tick can represent several censored observations. The comparison is descriptive; these unadjusted curves do not estimate a causal effect of sex.

8.2 Add risk counts and landmarks

survival_chart <- draw_survfit(
  fit,
  risk_times = c(0, 250, 500, 750, 1000),
  show_median = TRUE,
  landmarks = 365,
  xlab = "Days"
)
survival_chart

Dashed droplines locate median survival when the curve reaches 0.5. A plateau at 0.5 uses its midpoint, matching the survival package’s convention. Landmark labels show survival at the requested time, using the last step at or before that time. Curves and landmarks are not extended past a group’s last follow-up.

The risk table reports counts immediately before each labeled time. Explicit time headings identify the columns even when they differ from the axis ticks. Clicking a group in the legend toggles its curve, band, censor ticks, annotations, and risk row together.

For a simpler display, set show_ci = FALSE or show_censors = FALSE. Legend position and inside/outside placement use the same controls as other draw charts.

8.3 Use portable records

Extract one fitted curve with its estimator-defined starting point:

one_fit <- survival::survfit(
  survival::Surv(time, status) ~ 1, data = patients
)
steps <- survival::survfit0(one_fit)
curves <- data.frame(
  time = steps[["time"]],
  survival = steps[["surv"]],
  lower = steps[["lower"]],
  upper = steps[["upper"]],
  n_censor = steps[["n.censor"]],
  n_risk = steps[["n.risk"]]
)
draw_survival(curves, xlab = "Days")

Each group must have unique times and nonincreasing survival probabilities. Include its starting record explicitly; the renderer does not assume time zero. Missing confidence bounds leave gaps. Missing risk counts remain NA, rather than being changed to zero.

The same records can be drawn through a saved configuration:

config <- setup_SurvivalConfig(
  lower = "lower", upper = "upper",
  n_censor = "n_censor", n_risk = "n_risk",
  xlab = "Days", show_median = TRUE
)
draw(config, data = curves)

For an explicit risk table, supply list(curves = curves, risk = risk_records) and risk_table = TRUE. The risk frame has time, group, and n_risk columns, with the same requested times in every group. An ungrouped curve uses the label "Survival". Counts can be fractional when case weights were used.

Automatic risk-table extraction is limited to ordinary right-censored fits. With delayed entry, event-time counts cannot safely determine the risk set at arbitrary intervening times. Compute those counts from the original risk intervals and pass them as explicit records. Matrix-valued predicted curves must be selected one at a time; multistate and interval-censored fits are not covered by this interface.

8.4 Export

All displayed layers, including bands, ticks, labels, and risk rows, export as native vector geometry and text:

save_drawing(survival_chart, "survival.svg", width = 900, height = 650)
write_chart_config(config, "survival-config.json")
© 2026 E.D. Gennatas