1

I had trouble to generate a PDF file from a scatterplot created trough ggplot in a ShinyApp. I was succesful with a similar approach as the one from the answer from user juba to this stackoverflow question, but then the nearPoints() function I was using didn't work and gave an error message saying something about not being able to find the coordinfo. Then I used the ggsave option that Yihui Xie recommended, but with this strategy I'm getting files saved in the folder where my ShinyApp resides. I'm worried that if I try to use this in my ShinyApp hosted in the shinyapps.io site, there would be problems when trying to save these transient and temporal files. I also tried removing the file after the download is done but, anytime the plot is shown the file is created, so the file is created again after the copied file is downloaded. Here is only a sample (some important lines) of the code I used to allow for the download of the plot as a PDF file:

#### User Interface ----

# Show scatterplot with clicking capability
  plotOutput(outputId = "scatterplot", click = "plot_click")

# Show data table where data points clicked will be shown 
  dataTableOutput(outputId = "datatable")

 # Download button
     downloadButton('dlScatPlot', 'Download plot as PDF')

# Server ----

# Wrap the creation of the scatterplot in a function so the plot can be 
# downloaded as PDF
  makeScatPlot <- function() {
         ## some code to generate a ggplot plot
  }

# Create the scatterplot object the plotOutput function is expecting
  output$scatterplot <- renderPlot({
    # The file saved as ggsave originally will be first saved in the server,      and
    # then in the client side if the Download Button is used
    filename <- paste('scatterPlot_', Sys.Date(), '.pdf', sep='')
    ggsave(filename, makeScatPlot(), width = 11, height = 4, dpi = 300, units = "in")
    makeScatPlot()
  })
# Create data table showing points that have been clicked
  output$datatable <- DT::renderDataTable({
    rows <- nearPoints(df1, input$plot_click) %>%
      select(sample_ID, compound, DOI)
    DT::datatable(rows,  rownames = FALSE)
  })

output$dlScatPlot <- downloadHandler(
    filename = function() {
      paste('scatPlot_', Sys.Date(), '.pdf', sep='')
    },
    content = function(file) {
      file.copy(paste('scatPlot_', Sys.Date(), '.pdf', sep=''), file, overwrite = TRUE)

    # To avoid the accumulation of PDFs in the server
      file.remove(paste('scatPlot_', Sys.Date(), '.pdf', sep=''))
    }
  )

I guess it can cause trouble if I upload a ShinyApp script to shinyapps.io that creates one PDF file each time the plot is rendered, right?

Lorena R
  • 33
  • 6

2 Answers2

0

Instead of saving files to a specific path, you can save them as temporary file using tempfile(fileext = ".pdf"). Those files will be automatically removed once the session is over. So no need to remove them manually.

yusuzech
  • 5,896
  • 1
  • 18
  • 33
  • Thank you for the idea of using tempfile. My problem is I don't know how to use the tempfile() function. I guess it has to coexist with the ggsave function I'm using when using renderPlot() for the scatterplot output? To better show what I'm trying to do I edited the sample code I posted in my question – Lorena R Jul 26 '19 at 09:20
0

I finally came out with an obvious answer. I wasn't doing the straightforward thing that was call the ggsave in the downloadHandler call because I was using the Yihui answer directly. So, finally I just don't create the file inside the renderPlot() function, but in the downloadHandler where it rightfully should be.

 # Create the scatterplot object the plotOutput function is expecting
  output$scatterplot <- renderPlot({
    makeScatPlot()
  })
 # Create the button to download the scatterplot as PDF
 output$dlScatPlot <- downloadHandler(
    filename = function() {
      paste('scatterPlot_', Sys.Date(), '.pdf', sep='')
    },
    content = function(file) {
      ggsave(file, makeScatPlot(), width = 11, height = 4, dpi = 300, units = "in")
    }
    )

Using the above code, everything (including the nearPoints call) works now :)

Lorena R
  • 33
  • 6