kassambara / survminer

Survival Analysis and Visualization
https://rpkgs.datanovia.com/survminer/
501 stars 162 forks source link

Enhancement: nudge lines at 100% #551

Open nickp60 opened 3 years ago

nickp60 commented 3 years ago

This isn't a bug, but a suggested enhancement. Prism does something similar they call nudging: https://www.graphpad.com/guides/prism/latest/user-guide/using_change_plotting_order_survival_2.htm

Expected behavior

It would be nice to see all the groups at 100% survival.

Actual behavior

All the surviving groups overlap eachother at 100%

Steps to reproduce the problem

Suggested change:

# example survival fit, from docs
   require("survival")
  fit<- survfit(Surv(time, status) ~ sex, data = lung)

  # Basic survival curves
  gg <- ggsurvplot(fit, data = lung)

  if(nudge){
    # this mess puls apart the ggplot/ggsuv object and manually manipulates the values to avoid overlap at the 100% survival line. 
# Jitter ammount is computed using the numeric factor level of the color used for grouping.  Not elegant, but it works in my limited testing.
    gg_decon <- ggplot_build(gg$plot)
    ng <- length(unique(gg_decon$data[[1]]$colour))
   # modify the lines 
    gg_decon$data[[1]] <-  gg_decon$data[[1]] %>%
      mutate(y=ifelse(y==1, 1 + (.01*as.numeric(as.factor(colour))), y))
   # modify the censor point
    gg_decon$data[[3]] <-  gg_decon$data[[3]] %>%
      mutate(y=ifelse(y==1, 1 + (.01*as.numeric(as.factor(colour))), y))
   # from https://ggplot2-book.org/internals.html
    gtable <- ggplot_gtable(gg_decon)
    grid::grid.newpage()
    grid::grid.draw(gtable)
    return(invisible(gtable))
  } else{
    return(gg)
  }

Results

Here I am showing my data, as it has more groups than the lung data Old Version:

Screen Shot 2021-08-27 at 12 45 24 AM

Nudged Version:

Screen Shot 2021-08-27 at 12 44 56 AM

session_info()

R version 4.0.3 (2020-10-10)
Platform: x86_64-apple-darwin17.0 (64-bit)
Running under: macOS Big Sur 10.16

Matrix products: default
LAPACK: /Library/Frameworks/R.framework/Versions/4.0/Resources/lib/libRlapack.dylib

locale:
[1] en_US.UTF-8/en_US.UTF-8/en_US.UTF-8/C/en_US.UTF-8/en_US.UTF-8

attached base packages:
[1] grid      stats     graphics  grDevices utils     datasets  methods   base     

other attached packages:
 [1] RSQLite_2.2.7        stringr_1.4.0        survival_3.2-11      survminer_0.4.9      ggpubr_0.4.0        
 [6] lubridate_1.7.10     dplyr_1.0.7          dbplyr_2.1.1         tibble_3.1.2         DBI_1.1.1           
[11] dygraphs_1.1.1.6     plotly_4.9.4.1       ggplot2_3.3.5        shinydashboard_0.7.1 shiny_1.6.0         

loaded via a namespace (and not attached):
 [1] xts_0.12.1         bit64_4.0.5        RColorBrewer_1.1-2 httr_1.4.2         R.cache_0.15.0     tools_4.0.3       
 [7] backports_1.2.1    bslib_0.2.5.1      utf8_1.2.1         R6_2.5.0           lazyeval_0.2.2     colorspace_2.0-2  
[13] withr_2.4.2        tidyselect_1.1.1   gridExtra_2.3      bit_4.0.4          curl_4.3.2         compiler_4.0.3    
[19] cli_3.0.1          labeling_0.4.2     sass_0.4.0         scales_1.1.1       survMisc_0.5.5     readr_2.0.0       
[25] digest_0.6.27      foreign_0.8-81     R.utils_2.10.1     rio_0.5.27         pkgconfig_2.0.3    htmltools_0.5.1.1 
[31] sourcetools_0.1.7  styler_1.5.1       fastmap_1.1.0      htmlwidgets_1.5.3  rlang_0.4.11       readxl_1.3.1      
[37] rstudioapi_0.13    farver_2.1.0       jquerylib_0.1.4    generics_0.1.0     zoo_1.8-9          jsonlite_1.7.2    
[43] crosstalk_1.1.1    R.oo_1.24.0        zip_2.2.0          car_3.0-11         magrittr_2.0.1     Matrix_1.3-4      
[49] Rcpp_1.0.7         munsell_0.5.0      fansi_0.5.0        abind_1.4-5        R.methodsS3_1.8.1  lifecycle_1.0.0   
[55] stringi_1.7.3      yaml_2.2.1         carData_3.0-4      blob_1.2.1         promises_1.2.0.1   forcats_0.5.1     
[61] crayon_1.4.1       lattice_0.20-44    haven_2.4.1        splines_4.0.3      hms_1.1.0          knitr_1.33        
[67] pillar_1.6.1       ggsignif_0.6.2     glue_1.4.2         data.table_1.14.0  vctrs_0.3.8        tzdb_0.1.2        
[73] httpuv_1.6.1       cellranger_1.1.0   gtable_0.3.0       purrr_0.3.4        tidyr_1.1.3        rematch2_2.1.2    
[79] km.ci_0.5-2        assertthat_0.2.1   cachem_1.0.5       xfun_0.24          openxlsx_4.2.4     mime_0.11         
[85] xtable_1.8-4       broom_0.7.8        rstatix_0.7.0      later_1.2.0        rsconnect_0.8.24   viridisLite_0.4.0 
[91] tinytex_0.32       memoise_2.0.0      KMsurv_0.1-5       ellipsis_0.3.2  
mariefbourdon commented 1 year ago

@nickp60 This was super helpful, thanks !