rshinyr-markdownpngtemp

Save reactive plot to temp directory as png from shiny app


This question is quite basic and related to some questions before How to save reactive plot as png to working directory in a shiny app

I had to change my strategy creating a plot from a shiny app in Rmarkdown.

For this I need to accomplish this simple task:

How can I save this plot to the temp folder as png?

Background: After saving to temp folder I will transfer it to R markdown to create a report.

library(shiny)

ui <- basicPage(
  plotOutput("plot1"),
)

server <- function(input, output) {
  output$plot1 <- renderPlot({
    plot(mtcars$wt, mtcars$mpg)
  })
}
shinyApp(ui, server)

Update: My original code looks like this. I can't provide a reproducible example with this because it is to complex:

How can I implement the answer by ismirsehregal to this code:

# plot: Radarplot ------

output$radar <- renderChartJSRadar({
  chartJSRadar(PSA_13()[,c(1,2,6)],
               main = "XXX",
               maxScale = 100, scaleStepWidth = 10, scaleStartValue = 0, labelSize = 12, 
               addDots = TRUE, showToolTipLabel = TRUE, showLegend = TRUE, lineAlpha = 0.8, 
               polyAlpha = 0.2, responsive = FALSE, 
               colMatrix = col2rgb(c("orange", "navy" ,"grey")))
})

# create markdown report with radar plot ----------------------------------

output$report <- downloadHandler(
  filename = "report.pdf",
    content = function(file) {
      td <- tempdir()
      tempReport <- file.path(td, "report.Rmd")
      tempLogo <- file.path(td, "logo.png")
      file.copy("report.Rmd", tempReport, overwrite = TRUE)
      file.copy("logo.png", tempLogo, overwrite = TRUE)
    
    params <- list(scores = PSA_13()[,c(1,2,6)])
                   
    
    rmarkdown::render(tempReport, output_file = file,
                      params = params,
                      envir = new.env(parent = globalenv())
    )
  }
)

report.Rmd

    ---
geometry: margin=20truemm
fontfamily: mathpazo
fontsize: 11pt
documentclass: article
classoption: a4paper
urlcolor: blue
output: 
    pdf_document
header-includes:
   - \usepackage{fancyhdr}
   - \pagestyle{fancy}
   - \rhead{\includegraphics[width = .05\textwidth]{logo.png}}
params: 
    scores: NA
    plot_object: NA
---
\pagenumbering{gobble}

```{r setup, include=FALSE}
knitr::opts_chunk$set()
library(draw)
```

```{r rectangle, echo=FALSE}
drawBox(x =1.3, y = 3.7, width = 2.5, height = 1)
```

\vspace{-80truemm}

```{r plotout, echo=FALSE, message=FALSE, out.width='100%'}
params$plot_object
```


<!-- ```{r, echo=FALSE, out.width="100%", } -->
<!-- chartJSRadar(params$scores, width = 700, height = 700, -->
<!--              main = "Peritoneal Surface Calculator Radarchart", -->
<!--              maxScale = 100, -->
<!--              scaleStepWidth = 10, -->
<!--              scaleStartValue = 0, -->
<!--              labelSize = 14, -->
<!--              addDots = TRUE, -->
<!--              showToolTipLabel = FALSE, -->
<!--              showLegend = TRUE, -->
<!--              lineAlpha = 0.8, -->
<!--              polyAlpha = 0.2, -->
<!--              responsive = FALSE, -->
<!--              colMatrix = col2rgb(c("orange", "navy" ,"grey"))) -->
<!-- ``` -->

I feel quite near to the solution and I am very grateful for your time!


Solution

  • There is no need to save a temporary png file. We can use recordPlot instead:

    library(shiny)
    library(datasets)
    
    writeLines(con = "report.Rmd", text = "---
    title: 'Plot report'
    output: html_document
    params:
      plot_object: NA
    ---
    
    ```{r plotout, echo=FALSE, message=FALSE, out.width='100%'}
    params$plot_object
    ```")
    
    ui = fluidPage(
      plotOutput("plot1"),
      downloadButton("report_button", "Generate report")
    )
    
    server = function(input, output, session) {
      reactivePlot1 <- reactive({
        plot(mtcars$wt, mtcars$mpg)
        recordPlot()
      })
      
      output$plot1 <- renderPlot({
        reactivePlot1()
      })
      
      output$report_button <- downloadHandler(
        filename = "report.html",
        content = function(file) {
          tempReport <- tempfile(fileext = ".Rmd") # make sure to avoid conflicts with other shiny sessions if more params are used
          file.copy("report.Rmd", tempReport, overwrite = TRUE)
          rmarkdown::render(tempReport, output_format = "html_document", output_file = file, output_options = list(self_contained = TRUE),
                            params = list(plot_object = reactivePlot1())
          )
        }
      )
    }
    
    shinyApp(ui, server)
    

    Please see my related answer here.


    After OPs update - using dummy data:

    app.R:

    library(shiny)
    library(radarchart)
    
    scores <- data.frame("Label"=c("Communicator", "Data Wangler", "Programmer",
                                   "Technologist",  "Modeller", "Visualizer"),
                         "Rich" = c(9, 7, 4, 5, 3, 7),
                         "Andy" = c(7, 6, 6, 2, 6, 9),
                         "Aimee" = c(6, 5, 8, 4, 7, 6))
    
    ui = fluidPage(
      chartJSRadarOutput("radar", width = "450", height = "300"),
      downloadButton("report", "Generate report")
    )
    
    server = function(input, output, session) {
      reactiveRadar <- reactive({
        chartJSRadar(scores, maxScale = 10, showToolTipLabel=TRUE)
      })
      
      # plot: Radarplot ------
      output$radar <- renderChartJSRadar({
        reactiveRadar()
      })
      
      # create markdown report with radar plot ----------------------------------
      
      output$report <- downloadHandler(
        filename = "report.html",
        content = function(file) {
          td <- tempdir()
          tempReport <- file.path(td, "report.Rmd")
          # tempLogo <- file.path(td, "logo.png")
          file.copy("report.Rmd", tempReport, overwrite = TRUE)
          # file.copy("logo.png", tempLogo, overwrite = TRUE)
          
          params <- list(scores = "Test", plot_object = reactiveRadar()) # scores = PSA_13()[,c(1,2,6)]
          
          rmarkdown::render(tempReport, output_file = file,
                            params = params,
                            envir = new.env(parent = globalenv())
          )
        }
      )
    }
    
    shinyApp(ui, server)
    

    report.Rmd:

    ---
    geometry: margin=20truemm
    fontfamily: mathpazo
    fontsize: 11pt
    documentclass: article
    classoption: a4paper
    urlcolor: blue
    output: 
        html_document
    header-includes:
       - \usepackage{fancyhdr}
       - \pagestyle{fancy}
       # - \rhead{\includegraphics[width = .05\textwidth]{logo.png}}
    params: 
        scores: NA
        plot_object: NA
    ---
    \pagenumbering{gobble}
    
    ```{r setup, include=FALSE}
    knitr::opts_chunk$set()
    library(draw)
    ```
    
    ```{r rectangle, echo=FALSE}
    drawBox(x =1.3, y = 3.7, width = 2.5, height = 1)
    ```
    
    \vspace{-80truemm}
    
    ```{r plotout, echo=FALSE, message=FALSE, out.width='100%'}
    params$plot_object
    ```