Search code examples
rggplot2survival-analysiscox-regressionsurvival

Customising line type in adjusted survival curves ggadjustedcurves (survminer, ggplot2)


I'm trying to plot an adjusted survival curve, but struggling with changing the line types by group. I'm able to customise other aspects of the plot using typical ggplot2 language, but I've hit a wall with changing line type.

Example:

library(survival)
library(survminer)

fit2 <- coxph( Surv(stop, event) ~ size + strata(rx), data = bladder )

ggadjustedcurves(fit2,
                 variable = "rx", 
                 data = bladder,
                 method = "average",
                 palette = c("#E69F00", "#56B4E9"),
                 size = 1.3,
                 legend = "right",
                 legend.title = expression(bold("Legend title")),
                 xlab = "Time",
                 font.legend = 12) +
  theme(legend.text.align = 0.5)

I've tried adding in:

geom_line( aes( linetype = c(1, 2) )
add.params = list(linetype = c(1, 2))

and just

linetype = c(1, 2)

but nothing seems to work.


Solution

  • First you need to look at the code.

    ggadjustedcurves
    

    It appears that ggadjustedcurves passes all it arguments on to helper functions that depend on the "method" argument, in this case "average", so now look at that (hidden) function:

     getAnywhere( ggadjustedcurves.average )
    

    And note that there is no provision to accept additional arguments beyond the few that are defined in the "master function", i.e. no use of R's ellipsis mechanism or specifications of other possible aes-arguments besides size. (It's also not using geom_line.) So you need to change both the master function and the helper function to accept a "linetype" argument. Here I show how to modify the helper function (although this needs to be done to the ggadjustedcurves function as well and maybe the rest of the helper functions if you want this to be completely general):

    assignInNamespace('ggadjustedcurves.average',  
    
      function (data, fit, variable, size = 1, ..., linetype=linetype) 
        {
        time <- surv <- NULL
        lev <- sort(unique(data[, variable]))
        pred <- survexp(as.formula(paste("~", variable)), data = data, 
                        ratetable = fit)
        curve <- data.frame(time = rep(c(0, pred$time), length(lev)), 
                            variable = factor(rep(lev, each = 1 + length(pred$time))), 
                            surv = c(rbind(1, pred$surv)))
        ggplot(curve, aes(x = time, y = surv, color = variable)) + 
            geom_step(size = size, ..., linetype=linetype)  # not geom_line
        }, 
       pos="package:survminer")
    

    enter image description here

    If you do an SO search on "geom_segment linetype" you find that geom_segment (which is what geon_step uses) is not constructed in a manner that makes it easy to give it short vectors to modify "contiguous" lengths of step function results. See ggplot error using linetype and group aesthetics . This means you would need to use a for-loop or lapply to build separate "step-curves" if you need different line types.