High-level packages like survminer make it easy to get quick results/plots, but makes it harder to customize compared to building out the plots yourself using ggplot2 directly. The object returned from ggsurvplot() does not carry the necessary class to build these custom aesthetics on top of it.
In this case, it is probably best to build the plot from scratch like this:
library(tidyverse)
library(ggplot2)
library(pammtools)
library(survival)
library(scales)
df <- data.frame(
Time = c(1596,1514,356,2085,1921,318,83,328,
815,1854,159,240,821,720,2315,1800,99,205,177,1200),
Status = c(2, 2, 1, 1, 1, 2, 1, 2, 2, 1, 2, 2, 2, 1, 1, 2, 2, 2, 2, 1)
)
sf <- survfit(Surv(Time, Status) ~ 1, data = df)
df2 <-
tibble(
time = sf$time,
surv = sf$surv,
lower = sf$lower,
upper = sf$upper
) %>%
mutate(time = time / 30)
msurv <- df2 %>%
filter(surv <=0.5) %>%
slice_min(time)
censor_data <-
df %>%
filter(Status==1) %>%
mutate(time = Time / 30) %>%
left_join(df2)
#> Joining, by = "time"
df2 %>%
ggplot(aes(time, surv)) +
geom_stepribbon(
aes(ymin = lower, ymax = upper),
alpha = 0.4, fill = "turquoise2"
) +
geom_step(size = 1, color = "turquoise2") +
geom_point(data = censor_data, aes(time, surv), shape = 3) +
annotate("segment", x = 0, xend = msurv$time,
y = 0.5, yend = 0.5, lty = 2) +
annotate("segment", x = msurv$time, xend = msurv$time,
y = 0, yend = 0.5, lty = 2) +
scale_y_continuous(labels = percent_format()) +
scale_x_continuous(
breaks = round(c(seq(0, 40, by = 10), msurv$time, seq(60, 80, by = 10)), 1)
) +
labs(
x = "Time (months)",
y = "Survival probability (%)"
) +
theme_classic(16)
