Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Saving ggsurvplot() #152

Open
kassambara opened this issue Feb 19, 2017 · 18 comments · May be fixed by #522
Open

Saving ggsurvplot() #152

kassambara opened this issue Feb 19, 2017 · 18 comments · May be fixed by #522

Comments

@kassambara
Copy link
Owner

e-mail from a user

Hi Alboukadel,
How are you? I hope you’re doing good. I was trying to save a KM plot using survminer. However, when I try to save the figure with ggsave I got an error message as below. I did some online search but could not really find a solution. Could you please help?
Thanks in advance!
Serigne

require("survival")
require("survminer")
 
fit<- survfit(Surv(time, status) ~ sex, data = lung)
 
# Drawing survival curves
ggsurvplot(fit)
 
# Change font size, style and color
#++++++++++++++++++++++++++++++++++++
## Not run:
# Change font size, style and color at the same time
pp = ggsurvplot(fit, main = "Survival curve",
           font.main = c(16, "bold", "darkblue"),
           font.x = c(14, "bold.italic", "red"),
           font.y = c(14, "bold.italic", "darkred"),
           font.tickslab = c(12, "plain", "darkgreen"))
ggsave("C:\\serigne\\KMsurvival.jpeg", plot=pp)
Saving 6.1 x 7.27 in image
Error in UseMethod("grid.draw") :
  no applicable method for 'grid.draw' applied to an object of class "c('ggsurvplot', 'list')"
@kassambara
Copy link
Owner Author

kassambara commented Feb 19, 2017

ggsurvplot() returns a list of ggplots containing survival curves and optionally the risk table. You can’t directly save the list using ggsave(), but you can save the output of print(ggsurvplot).

First, please install the latest version of survminer:

if(!require(devtools)) install.packages("devtools")
devtools::install_github("kassambara/survminer", build_vignettes = FALSE)

Then, type this:

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

require("survminer")
survp <- ggsurvplot(fit, risk.table = TRUE)
ggsave(file = "ggsurv.pdf", print(survp))

It should work.

@VincentGuyader
Copy link

Hi,
How can I use ggsave if I dont need the "number at risk table" ?

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

require("survminer")
survp <- ggsurvplot(fit, risk.table = FALSE)
ggsave(file = "ggsurv.pdf", print(survp))

Saving 4.46 x 7 in image
Error in UseMethod("grid.draw") :
no applicable method for 'grid.draw' applied to an object of class "list"

@kassambara
Copy link
Owner Author

Hi,

To save ggsurvplot + risktable, use this:

pdf("survplot.pdf")
print(survp, newpage = FALSE)
dev.off()

To save only survival plots without the risk table, use this:

pdf("survplot.pdf")
print(survp$plot, newpage = FALSE)
dev.off()

or use this:

ggsave("survplot.pdf", surp$plot)

@Phil-T
Copy link

Phil-T commented Sep 4, 2017

Im getting a similar error. Please see my code below.

fit<- survfit(Surv(time, dead) ~ copy_number, data = datain)
p <- ggsurvplot(fit, conf.int = TRUE, pval = TRUE,
main = "Survival",
palette = c("#ff0000", "#0000ff"),
font.main = c(10, "bold"),
font.x = c(8, "bold"),
font.y = c(8, "bold"),
font.tickslab = c(6, "bold"),
pval.size = 2,
size = 0.2,
censor.size = 1,
legend = "bottom"
)
p$plot <- p$plot + theme(legend.text = element_text(size = 4),
legend.title = element_text("", size = 4),
legend.key.size = unit(0.2, "cm"))

ggsave(filename= "/home/philserver/Desktop/mt_amp.tiff", print(p), device = "tiff", height = 2, width = 2, dpi = 300)

Error in UseMethod("grid.draw") :
no applicable method for 'grid.draw' applied to an object of class "list"

In spite of this error, the plot is still saved. However, the error stops the R pipeline I have written, and the other dozen graphs in my pipeline are not generated. Is there a way to resolve the issue of saving ggsurvplots without throwing an error?

@kassambara
Copy link
Owner Author

You can't use, the standard ggsave(), because ggsurvplot() always generates an object of class list, even if you set risk.table to FALSE. I think that I already suggested a solution to this issue. Please let me know if the solution works for you.

@kassambara
Copy link
Owner Author

The function ggpubr::ggexport() should work also for a list of ggplots, which are not supported by ggsave

@jvanlunenburg
Copy link

To anyone reading this, there is still no ggsave method for ggsurvplot objects.

@kassambara
Copy link
Owner Author

no, let's open this issue

@kassambara kassambara reopened this Jul 24, 2020
@chunjie-sam-liu
Copy link

chunjie-sam-liu commented Jan 20, 2021

ggsave(
  filename ='os-plot.pdf',
  plot = print(os.plot, newpage = FALSE),
  device = 'pdf',
  path = 'data/output',
  width = 8,
  height = 9
)

Worked for me.

@mjakubczak mjakubczak linked a pull request Mar 18, 2021 that will close this issue
@DKBurnsBresMed
Copy link

DKBurnsBresMed commented Jul 30, 2021

This still does not work in version 0.4.9 e.g.:

ggsave(filename = "./debug/test_picture.png",plot = print(obj), device = "png")

produces a blank image for a simple Kaplan-Meier plot with number at risk table. generated with survminer.

Similarly the producing a plot to pdf method produces an unreadable pdf (error on loading).

UPDATE: the ggexport method does work, producing one blank image and one plot. The full plot is produced with the name (using the above example) test_picture002.png (001 is blank).

ggexport(filename = "./debug/test_picture.png",plot = obj, device = "png")

Hopefully useful for someone!

@sstandage
Copy link

Neither the ggsave nor the ggexport works well for me.

I'm getting blank output with ggsave whether I try to save as png or pdf. ggexport will allow me to save as a png, but for publication I need it in pdf. To get a pdf, I have to export using the RStudio utility and some elements are not rendered accurately. Any more ideas/changes?

@adayim
Copy link

adayim commented Oct 8, 2021

There's a fix already, but you can use the code before it's been updated in the CRAN

grid.draw.ggsurvplot <- function(x){
  survminer:::print.ggsurvplot(x, newpage = FALSE)
}

Run this function before you save your plot using ggsave to save your plot.

Full working example

The code below should save the survival plot with risk table.

library("survival")
library("survminer")

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

p <- ggsurvplot(fit, risk.table = TRUE)

# add method to grid.draw
grid.draw.ggsurvplot <- function(x){
  survminer:::print.ggsurvplot(x, newpage = FALSE)
}

# Remember to pass object `p`.
ggsave("survival.png", plot = p, 
       dpi=300, width = 10, height = 7, units = "in")

@adayim
Copy link

adayim commented Dec 18, 2021

@mleipzig
It works perfectly fine, I tried the all the code with the first code. You forgot to pass the plot object. The ggsurvplot function returns a ggsurvplot object, not a ggplot object and it will not write anything to last_plot(). Read ggsave function help thoroughly. I think you should correct your plot saving code:

ggsave("one_year_survival.tiff", plot = p, device="tiff", dpi=300, width = 20, height = 7, units = "in")

@wiedenhoeft
Copy link

None of these work for me, the best I get is the last plot being saved , i.e. the KM plot if there is no risk table, or the risk table alone.

@wiedenhoeft
Copy link

wiedenhoeft commented Jan 13, 2022

This works for me: ggsave(file="survival.pdf", plot=ggarrange(g$plot, g$table, nrow=2, ncol=1, heights=c(3,1)))

But this would have to be manually adapted based on the number of subplots. Also, the x-axes become misaligned.

This function is a workaround

save_ggsurvplot <- function(filename,
g,
rel_heights=c(3,1,1,1)){
nrplots=length(g)-2
ggsave(file=filename,
plot=ggarrange(plotlist=g[1:nrplots],
nrow=nrplots,
ncol=1,
align="v",
heights=rel_heights[1:nrplots]))
}

@CorradoLanera
Copy link

Maybe it could be possible to convert the res object evaluated in ggsurvplot::print.ggsurvplot to a proper ggplot object and return it.

In the meantime, the following behind-the-scenes workaround, seems working to me:

library("survival")
library("survminer")
#> Loading required package: ggplot2
#> Loading required package: ggpubr
#> 
#> Attaching package: 'survminer'
#> The following object is masked from 'package:survival':
#> 
#>     myeloma

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

With risk table

gg_risk <- ggsurvplot(fit, risk.table = TRUE)
risk_png <- tempfile("risk", fileext = ".png")
risk_png |>
  ggsave(
    plot = survminer:::.build_ggsurvplot(gg_risk)
  )
#> Saving 7 x 5 in image
if (!interactive() && requireNamespace("knitr")) {
  knitr::include_graphics(risk_png)
}

Without risk table

gg_norisk <- ggsurvplot(fit, risk.table = FALSE)
norisk_png <- tempfile("norisk", fileext = ".png")
norisk_png |>
  ggsave(
    plot = survminer:::.build_ggsurvplot(gg_norisk)
  )
#> Saving 7 x 5 in image
if (!interactive() && requireNamespace("knitr")) {
  knitr::include_graphics(norisk_png)
}

Created on 2022-03-11 by the reprex package (v2.0.1)

Session info
sessioninfo::session_info()
#> - Session info ---------------------------------------------------------------
#>  setting  value
#>  version  R version 4.1.3 (2022-03-10)
#>  os       Windows 10 x64 (build 22000)
#>  system   x86_64, mingw32
#>  ui       RTerm
#>  language (EN)
#>  collate  English_United States.1252
#>  ctype    English_United States.1252
#>  tz       Europe/Berlin
#>  date     2022-03-11
#>  pandoc   2.14.0.3 @ C:/Program Files/RStudio/bin/pandoc/ (via rmarkdown)
#> 
#> - Packages -------------------------------------------------------------------
#>  package     * version date (UTC) lib source
#>  abind         1.4-5   2016-07-21 [1] CRAN (R 4.1.1)
#>  assertthat    0.2.1   2019-03-21 [1] RSPM (R 4.1.0)
#>  backports     1.4.1   2021-12-13 [1] RSPM (R 4.1.0)
#>  broom         0.7.12  2022-01-28 [1] RSPM (R 4.1.0)
#>  car           3.0-12  2021-11-06 [1] CRAN (R 4.1.2)
#>  carData       3.0-5   2022-01-06 [1] RSPM (R 4.1.0)
#>  cli           3.2.0   2022-02-14 [1] RSPM (R 4.1.0)
#>  colorspace    2.0-3   2022-02-21 [1] CRAN (R 4.1.2)
#>  crayon        1.5.0   2022-02-14 [1] RSPM (R 4.1.0)
#>  curl          4.3.2   2021-06-23 [1] RSPM (R 4.1.0)
#>  data.table    1.14.2  2021-09-27 [1] CRAN (R 4.1.2)
#>  DBI           1.1.2   2021-12-20 [1] RSPM (R 4.1.0)
#>  digest        0.6.29  2021-12-01 [1] RSPM (R 4.1.0)
#>  dplyr         1.0.8   2022-02-08 [1] CRAN (R 4.1.2)
#>  ellipsis      0.3.2   2021-04-29 [1] RSPM (R 4.1.0)
#>  evaluate      0.15    2022-02-18 [1] RSPM (R 4.1.0)
#>  fansi         1.0.2   2022-01-14 [1] CRAN (R 4.1.2)
#>  farver        2.1.0   2021-02-28 [1] RSPM (R 4.1.0)
#>  fastmap       1.1.0   2021-01-25 [1] RSPM (R 4.1.0)
#>  fs            1.5.2   2021-12-08 [1] RSPM (R 4.1.0)
#>  generics      0.1.2   2022-01-31 [1] RSPM (R 4.1.0)
#>  ggplot2     * 3.3.5   2021-06-25 [1] RSPM (R 4.1.0)
#>  ggpubr      * 0.4.0   2020-06-27 [1] RSPM (R 4.1.0)
#>  ggsignif      0.6.3   2021-09-09 [1] RSPM (R 4.1.0)
#>  ggtext        0.1.1   2020-12-17 [1] RSPM (R 4.1.0)
#>  glue          1.6.2   2022-02-24 [1] CRAN (R 4.1.2)
#>  gridExtra     2.3     2017-09-09 [1] RSPM (R 4.1.0)
#>  gridtext      0.1.4   2020-12-10 [1] RSPM (R 4.1.0)
#>  gtable        0.3.0   2019-03-25 [1] RSPM (R 4.1.0)
#>  highr         0.9     2021-04-16 [1] RSPM (R 4.1.0)
#>  htmltools     0.5.2   2021-08-25 [1] CRAN (R 4.1.2)
#>  httr          1.4.2   2020-07-20 [1] RSPM (R 4.1.0)
#>  km.ci         0.5-2   2009-08-30 [1] RSPM (R 4.1.0)
#>  KMsurv        0.1-5   2012-12-03 [1] RSPM (R 4.1.0)
#>  knitr         1.37    2021-12-16 [1] RSPM (R 4.1.0)
#>  labeling      0.4.2   2020-10-20 [1] RSPM (R 4.1.0)
#>  lattice       0.20-45 2021-09-22 [2] CRAN (R 4.1.3)
#>  lifecycle     1.0.1   2021-09-24 [1] CRAN (R 4.1.2)
#>  magrittr      2.0.2   2022-01-26 [1] CRAN (R 4.1.2)
#>  markdown      1.1     2019-08-07 [1] RSPM (R 4.1.0)
#>  Matrix        1.4-0   2021-12-08 [2] CRAN (R 4.1.3)
#>  mime          0.12    2021-09-28 [1] CRAN (R 4.1.1)
#>  munsell       0.5.0   2018-06-12 [1] RSPM (R 4.1.0)
#>  pillar        1.7.0   2022-02-01 [1] RSPM (R 4.1.0)
#>  pkgconfig     2.0.3   2019-09-22 [1] RSPM (R 4.1.0)
#>  png           0.1-7   2013-12-03 [1] RSPM (R 4.1.0)
#>  purrr         0.3.4   2020-04-17 [1] RSPM (R 4.1.0)
#>  R.cache       0.15.0  2021-04-30 [1] CRAN (R 4.1.2)
#>  R.methodsS3   1.8.1   2020-08-26 [1] CRAN (R 4.1.1)
#>  R.oo          1.24.0  2020-08-26 [1] CRAN (R 4.1.1)
#>  R.utils       2.11.0  2021-09-26 [1] CRAN (R 4.1.2)
#>  R6            2.5.1   2021-08-19 [1] CRAN (R 4.1.2)
#>  ragg          1.2.2   2022-02-21 [1] RSPM (R 4.1.0)
#>  Rcpp          1.0.8   2022-01-13 [1] RSPM (R 4.1.0)
#>  reprex        2.0.1   2021-08-05 [1] CRAN (R 4.1.2)
#>  rlang         1.0.2   2022-03-04 [1] CRAN (R 4.1.2)
#>  rmarkdown     2.13    2022-03-10 [1] CRAN (R 4.1.3)
#>  rstatix       0.7.0   2021-02-13 [1] RSPM (R 4.1.0)
#>  rstudioapi    0.13    2020-11-12 [1] RSPM (R 4.1.0)
#>  scales        1.1.1   2020-05-11 [1] RSPM (R 4.1.0)
#>  sessioninfo   1.2.2   2021-12-06 [1] RSPM (R 4.1.0)
#>  stringi       1.7.6   2021-11-29 [1] CRAN (R 4.1.1)
#>  stringr       1.4.0   2019-02-10 [1] RSPM (R 4.1.0)
#>  styler        1.6.2   2021-09-23 [1] CRAN (R 4.1.2)
#>  survival    * 3.3-1   2022-03-03 [1] CRAN (R 4.1.3)
#>  survminer   * 0.4.9   2021-03-09 [1] RSPM (R 4.1.0)
#>  survMisc      0.5.5   2018-07-05 [1] RSPM (R 4.1.0)
#>  systemfonts   1.0.4   2022-02-11 [1] RSPM (R 4.1.0)
#>  textshaping   0.3.6   2021-10-13 [1] CRAN (R 4.1.2)
#>  tibble        3.1.6   2021-11-07 [1] CRAN (R 4.1.2)
#>  tidyr         1.2.0   2022-02-01 [1] RSPM (R 4.1.0)
#>  tidyselect    1.1.2   2022-02-21 [1] RSPM (R 4.1.0)
#>  utf8          1.2.2   2021-07-24 [1] CRAN (R 4.1.2)
#>  vctrs         0.3.8   2021-04-29 [1] RSPM (R 4.1.0)
#>  withr         2.5.0   2022-03-03 [1] RSPM (R 4.1.0)
#>  xfun          0.30    2022-03-02 [1] RSPM (R 4.1.0)
#>  xml2          1.3.3   2021-11-30 [1] RSPM (R 4.1.0)
#>  xtable        1.8-4   2019-04-21 [1] RSPM (R 4.1.0)
#>  yaml          2.3.5   2022-02-21 [1] RSPM (R 4.1.0)
#>  zoo           1.8-9   2021-03-09 [1] RSPM (R 4.1.0)
#> 
#>  [1] C:/Users/corra/Documents/R/win-library/4.1
#>  [2] C:/Program Files/R/R-4.1.3/library
#> 
#> ------------------------------------------------------------------------------

@HuoJnx
Copy link

HuoJnx commented Mar 11, 2022

Maybe it could be possible to convert the res object evaluated in ggsurvplot::print.ggsurvplot to a proper ggplot object and return it.

In the meantime, the following behind-the-scenes workaround, seems working to me:

library("survival")
library("survminer")
#> Loading required package: ggplot2
#> Loading required package: ggpubr
#> 
#> Attaching package: 'survminer'
#> The following object is masked from 'package:survival':
#> 
#>     myeloma

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

With risk table

gg_risk <- ggsurvplot(fit, risk.table = TRUE)
risk_png <- tempfile("risk", fileext = ".png")
risk_png |>
  ggsave(
    plot = survminer:::.build_ggsurvplot(gg_risk)
  )
#> Saving 7 x 5 in image
if (!interactive() && requireNamespace("knitr")) {
  knitr::include_graphics(risk_png)
}

Without risk table

gg_norisk <- ggsurvplot(fit, risk.table = FALSE)
norisk_png <- tempfile("norisk", fileext = ".png")
norisk_png |>
  ggsave(
    plot = survminer:::.build_ggsurvplot(gg_norisk)
  )
#> Saving 7 x 5 in image
if (!interactive() && requireNamespace("knitr")) {
  knitr::include_graphics(norisk_png)
}

Created on 2022-03-11 by the reprex package (v2.0.1)

Session info

Work for me, thanks!

@kapsner
Copy link

kapsner commented May 27, 2022

Both examples (from @adayim and @CorradoLanera) work for me (with argument risk.table=TRUE). It would be very nice, if one of these could be added to the exported functions for the next CRAN release.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.