how to use ggsurvfit to add at risk table inside of KM plot and color code groups?

114 views Asked by At

I could not find syntax to add at risk table inside of KM plot and color code groups like SAS do. I know the package was published recently, so I'm not sure if there is any syntax for that.

I followed the guidance [https://www.danieldsjoberg.com/ggsurvfit/reference/add_risktable.html] to use ggsurvfit to generate KM plot.

1

There are 1 answers

6
Allan Cameron On

The examples are fairly clear on the help pages. Here's an example of a color-coded KM with a risk table, using the df_lung data frame that comes with the ggsurvfit package:

library(ggsurvfit)

survfit2(Surv(time, status) ~ sex, data = df_lung) %>%
  ggsurvfit() +
  scale_ggsurvfit(x_scales = list(breaks = seq(0, 30, by = 6))) +
  add_risktable()

enter image description here


EDIT

If you are looking for something more bespoke, with the risk table as part of the main panel, you can place the text directly in it, but it requires some precalculation:

library(ggsurvfit)
library(tidyverse)

survdat <- ggsurvfit(survfit2(Surv(time, status) ~ sex, data = df_lung))$data

risk_table <- survdat %>% 
  group_by(strata) %>% 
  filter(c(TRUE, diff(n.risk) != 0)) %>%
  mutate(timecut = cut(time, breaks = c(-Inf, 0, 6, 12, 18, 24, 30), 
                       include.lowest = FALSE)) %>%
  group_by(strata, timecut) %>%
  slice_max(time, n = 1) %>%
  filter(time < 30) %>%
  ungroup() %>%
  mutate(time = seq(0, 30, 6), .by = 'strata')

The plot is now:

ggplot(survdat, aes(time, estimate, color = strata)) +
  geom_hline(yintercept = 0:4 * 0.25, color = 'gray', linewidth = 0.25) +
  geom_segment(inherit.aes = FALSE, data = data.frame(x = seq(0, 30, 6)),
               color = 'gray', linewidth = 0.25,
               aes(x = x, xend = x, y = 0, yend = Inf)) +
  geom_step() +
  geom_text(aes(y = as.numeric(strata)*-0.1, label = n.risk),
            show.legend = FALSE, data = risk_table) +
  geom_hline(yintercept = 0) +
  scale_y_continuous('Survival Probability',
                     breaks = c(-0.1, -0.2, 0:4 * 0.25), 
                     labels = ~ c(paste('n at risk', 
                                  levels(survdat$strata)[.x[.x < 0] * -10]),
                                  scales::percent(.x[.x >= 0]))) +
  scale_x_continuous('Time (months)', breaks = seq(0, 30, 6)) +
  scale_color_manual(NULL, values = c('blue3', 'red4')) +
  theme_bw(base_size = 16) +
  theme(legend.position = 'bottom',
        panel.grid = element_blank())

enter image description here