Save graphics made in a brilliant application

I am trying to figure out how to use downloadButton to keep the plot brilliant. The example in the package demonstrates downloadButton / downloadHandler for saving CSV. I am going to make a reproducible example based on this.

For ui.R

 shinyUI(pageWithSidebar( headerPanel('Downloading Data'), sidebarPanel( selectInput("dataset", "Choose a dataset:", choices = c("rock", "pressure", "cars")), downloadButton('downloadData', 'Download Data'), downloadButton('downloadPlot', 'Download Plot') ), mainPanel( plotOutput('plot') ) )) 

For server.R

 library(ggplot2) shinyServer(function(input, output) { datasetInput <- reactive({ switch(input$dataset, "rock" = rock, "pressure" = pressure, "cars" = cars) }) plotInput <- reactive({ df <- datasetInput() p <-ggplot(df, aes_string(x=names(df)[1], y=names(df)[2])) + geom_point() }) output$plot <- renderPlot({ print(plotInput()) }) output$downloadData <- downloadHandler( filename = function() { paste(input$dataset, '.csv', sep='') }, content = function(file) { write.csv(datatasetInput(), file) } ) output$downloadPlot <- downloadHandler( filename = function() { paste(input$dataset, '.png', sep='') }, content = function(file) { ggsave(file,plotInput()) } ) }) 

If you answer this question, you are probably familiar with this, but in order for this to work, save the above in separate scripts ( ui.R and server.R ) in the ( foo ) folder in the working directory To launch a brilliant application run runApp("foo") .

Using ggsave , I get an error message indicating that ggsave cannot use the filename function (I think). If I use a standard graphics device (for example, below), Download Plot works without errors, but it does not write graphics.

Any advice on loading a graphing site is welcome.

+75
r shiny ggplot2
Feb 11 '13 at
source share
5 answers

I'm not sure if this question is still active, but this is the first one that appeared when searching for “saving graphs in a brilliant application”, so I would like to quickly add how to get ggsave to work with downloadHandler along the lines of the original question,

The alternative strategies suggested by juba using direct output instead of ggsave and the alternative strategy suggested by alexwhan both work fine, it's just for those who absolutely want to use ggsave in downloadHandler).

The problem reported by alexwhan is because ggsave is trying to map the file extension to the correct graphics device. However, the temporary file has no extension, so the match does not occur. This can be eliminated by specially configuring the device in the ggsave function ggsave , for example, in the source code example (for png):

 output$downloadPlot <- downloadHandler( filename = function() { paste(input$dataset, '.png', sep='') }, content = function(file) { device <- function(..., width, height) grDevices::png(..., width = width, height = height, res = 300, units = "in") ggsave(file, plot = plotInput(), device = device) } ) 

This call basically accepts the device function for png , which ggsave assigns internally (you can look at the ggsave function code to see the syntax jpg , pdf , etc.). Perhaps, ideally, you could specify the file extension (if it differs from the file name - as is the case here for the temporary file) as the ggsave parameter, but this option is not currently available in ggsave .




Minimal standalone working example:

 library(shiny) library(ggplot2) runApp(list( ui = fluidPage(downloadButton('foo')), server = function(input, output) { plotInput = function() { qplot(speed, dist, data = cars) } output$foo = downloadHandler( filename = 'test.png', content = function(file) { device <- function(..., width, height) { grDevices::png(..., width = width, height = height, res = 300, units = "in") } ggsave(file, plot = plotInput(), device = device) }) } )) sessionInfo() # R version 3.1.1 (2014-07-10) # Platform: x86_64-pc-linux-gnu (64-bit) # # locale: # [1] LC_CTYPE=en_US.UTF-8 LC_NUMERIC=C # [3] LC_TIME=en_US.UTF-8 LC_COLLATE=en_US.UTF-8 # [5] LC_MONETARY=en_US.UTF-8 LC_MESSAGES=en_US.UTF-8 # [7] LC_PAPER=en_US.UTF-8 LC_NAME=C # [9] LC_ADDRESS=C LC_TELEPHONE=C # [11] LC_MEASUREMENT=en_US.UTF-8 LC_IDENTIFICATION=C # # attached base packages: # [1] stats graphics grDevices utils datasets methods base # # other attached packages: # [1] ggplot2_1.0.0 shiny_0.10.1 # # loaded via a namespace (and not attached): # [1] bitops_1.0-6 caTools_1.17 colorspace_1.2-4 digest_0.6.4 # [5] formatR_1.0 grid_3.1.1 gtable_0.1.2 htmltools_0.2.6 # [9] httpuv_1.3.0 labeling_0.2 MASS_7.3-34 munsell_0.4.2 # [13] plyr_1.8.1 proto_0.3-10 Rcpp_0.11.2 reshape2_1.4 # [17] RJSONIO_1.3-0 scales_0.2.4 stringr_0.6.2 tools_3.1.1 # [21] xtable_1.7-3 

Update

In ggplot2 version 2.0.0, the ggsave function supports character input for the device parameter, which means that the temporary file created by downloadHandler can now be saved by calling ggsave , indicating that the extension used should be, for example, "pdf" (instead device function transfer). This simplifies the above example to the following

 output$downloadPlot <- downloadHandler( filename = function() { paste(input$dataset, '.png', sep='') }, content = function(file) { ggsave(file, plot = plotInput(), device = "png") } ) 
+54
Apr 6 '14 at
source share

Here's a solution that allows you to use ggsave to save brilliant graphics. It uses a boolean flag and text input to call ggsave() . Add this to the ui.R file inside the sidebarPanel :

 textInput('filename', "Filename"), checkboxInput('savePlot', "Check to save") 

Then add this to the server.R file instead of the current output$plot reactivePlot function:

 output$plot <- reactivePlot(function() { name <- paste0(input$filename, ".png") if(input$savePlot) { ggsave(name, plotInput(), type="cairo-png") } else print(plotInput()) }) 

Then the user can enter the desired file name in the text field (without extension) and mark the checkbox to save in the application directory. Uncheck the box to print the graph. I'm sure there are easier ways to do this, but at least now I can use ggsave and cairo in windows for more nice png graphics.

Please add any suggestions you may have.

+22
Feb 12 '13 at 22:58
source share

I was not able to get it to work with ggsave , but with a standard png() call, this looks fine.

I just changed the output$downloadPlot your server.R file:

  output$downloadPlot <- downloadHandler( filename = function() { paste(input$dataset, '.png', sep='') }, content = function(file) { png(file) print(plotInput()) dev.off() }) 

Please note that I had some problems with the gloss version 0.3, but it works with the latest from Github:

 library(devtools) install_github("shiny","rstudio") 
+20
Feb 11 '13 at 13:15
source share

This is an old but still the best hit when someone googles "R shiny save ggplot", so I will contribute to another workaround. Very simple ... call ggsave in the same function that displays your graph, which will save the graph as a file on the server.

 output$plot <- renderPlot({ ggsave("plot.pdf", plotInput()) plotInput() }) 

Then use downloadHandler and use file.copy() to write data from an existing file to the file parameter.

 output$dndPlot <- downloadHandler( filename = function() { "plot.pdf" }, content = function(file) { file.copy("plot.pdf", file, overwrite=TRUE) } ) 

It works for me.

+17
Jul 30 '14 at 5:08
source share

I also had problems creating a PDF file from a scatter plot created using ggplot in ShinyApp. I succeeded with an approach similar to the one used in juba, but then the nearPoints () function I used did not work and gave an error message telling me something about the inability to find the coordinates. Then I used the ggsave option recommended by Yihui Xie, but with this strategy I get the files saved in the folder where my ShinyApp is located. I am worried that if I try to use this in my ShinyApp hosted on shinyapps.io, there will be problems trying to save these temporary and temporary files. I also tried to delete the file after the download was completed, but every time a graph is displayed, the file is created, so the file is created again after the downloaded file is downloaded. Here is an example of the code I used for the download button:

  filename = function() { paste('boxPlot_', Sys.Date(), '.pdf', sep='') }, content = function(file) { file.copy(paste('boxPlot_', Sys.Date(), '.pdf', sep=''), file, overwrite = TRUE) # To avoid the accumulation of PDFs in the server file.remove(paste('boxPlot_', Sys.Date(), '.pdf', sep='')) } ) 

I suppose this might cause problems if I upload the ShinyApp script to shinyapps.io, which creates one PDF file each time the graph is rendered, right?

0
Jul 25 '19 at 14:02
source share



All Articles