0

I want to add survival percentages at the end of the curves. Doing so leads to the risk table not lining up with the graph (the graph width is reduced relative to the risk table width). Risk table and graph are not aligned

Code to reproduce the graph:

library(survival)
library(survminer)

fit<- survfit(Surv(time, status) ~ sex, data = lung)

ggsurvplot(fit, data = lung,

  risk.table = TRUE,
  tables.height = 0.2,
  ggtheme = theme_bw() # Change ggplot2 theme
)

time_cutoff = 600
survs = summary(fit, times=time_cutoff)$surv
labels = paste(round(survs*100), '%', sep='')
  
my_plot$plot <- my_plot$plot + coord_cartesian(ylim=c(0,1), xlim = c(0,time_cutoff), clip = 'on', expand=FALSE)
my_plot$plot <- my_plot$plot + scale_y_continuous(name=NULL, sec.axis=sec_axis(~., name=NULL, breaks =  survs, labels= labels)) 
my_plot

2 Answers2

2

There are a few ways to do this. Perhaps the easiest is to add a coord_cartesian to the my_plot$table object, then draw the plot and table with patchwork, which will align the panels

library(survival)
library(survminer)

fit<- survfit(Surv(time, status) ~ sex, data = lung)

my_plot <- ggsurvplot(fit, data = lung,
           risk.table = TRUE,
           tables.height = 0.2,
           ggtheme = theme_bw() 
)

time_cutoff = 600
survs = summary(fit, times=time_cutoff)$surv
labels = paste(round(survs*100), '%', sep='')

my_plot$plot <- my_plot$plot + 
  coord_cartesian(ylim = c(0, 1), 
                  xlim = c(0, time_cutoff), 
                  clip = 'on') + 
  scale_y_continuous(name = NULL, 
                     sec.axis = sec_axis(~., name = NULL, breaks = survs, 
                                         labels = labels)) 

my_plot$table <- my_plot$table +
  coord_cartesian(xlim = c(0, time_cutoff), 
                  clip = 'on')

library(patchwork)

(my_plot$plot / my_plot$table) + plot_layout(heights = c(3, 1))

Created on 2022-12-08 with reprex v2.0.2

Allan Cameron
  • 147,086
  • 7
  • 49
  • 87
  • Actually this doesn't exactly solve the problem. When "expand=False" is removed, the labels no longer line up with the right end of the survival curve. You can see that the 15% is a little higher then the point where the curve ends. Adding "expand=False" corrects this, but then the survival graph and the number at risk are again misaligned. – Gordon Lemmon Dec 12 '22 at 21:10
  • @GordonLemmon but how _could_ the numbers be aligned under 0 if `expand = FALSE`? Your options are either 1) to leave expansion on, 2) turn off clipping and remove the border around the table, or 3) muck about with panel and margin spaces until the numbers aligned (though then the panel outlines will be different widths in the plot and the table). I think the option I showed is the most elegant, but the second option might work reasonably well too. I will add it to my answer. – Allan Cameron Dec 12 '22 at 21:19
0

Thanks to Allen Cameron's answer for getting me 95% to the answer. Adding to his response, I have to modify the table the same way we modified the survival graph:

library(survival)
library(survminer)

fit<- survfit(Surv(time, status) ~ sex, data = lung)

# Customized survival curves
my_plot = ggsurvplot(fit, data = lung,
 # Add p-value and tervals
 risk.table = TRUE,
 tables.height = 0.2,
 ggtheme = theme_bw() # Change ggplot2 theme
)

time_cutoff = 600
survs = summary(fit, times=time_cutoff)$surv
labels = paste(round(survs*100), '%', sep='')
  
my_plot$plot <- my_plot$plot + coord_cartesian(ylim=c(0,1), xlim = c(-50,time_cutoff), clip = 'on', expand=FALSE)
my_plot$plot <- my_plot$plot + scale_y_continuous(name=NULL, sec.axis=sec_axis(~., name=NULL, breaks = survs, labels= labels)) 
table_ylim = ggplot_build(my_plot$table)$layout$panel_params[[1]]$y.range
my_plot$table <- my_plot$table + coord_cartesian(ylim=table_ylim, xlim = c(-50,time_cutoff), clip = 'on', expand=FALSE)
library(patchwork)
(my_plot$plot / my_plot$table) + plot_layout(heights = c(3,1))

survival plot with number at risk table

  • I don't understand what's different here than in my answer. – Allan Cameron Dec 12 '22 at 21:58
  • In my version the 15% matches up with the far right of the red survival curve. In your version it is slightly above. This is because expand=False was removed and the xlim values were therefore not faithfully followed. – Gordon Lemmon Dec 13 '22 at 22:19