1

I am wondering if it is possible to pass a plot object to Rmarkdown document when generating a downloadable report using shiny?

For instance,I have a P2 plotly object, I want to pass it to Rmarkdown document.

I know I can put the code in Rmarkdown and generate the plot, but I don't to do it here

output$Plot <- plotly::renderPlotly({
p <- ggplot(data=iris, aes(x = Sepal.Length, y = Sepal.Width)) +
      geom_point(aes(color=Species, shape=Species)) +
      labs(title = "Iris sepal width vs length")
P2 <- ggplotly(p)
})

How can I pass it in downloadHandler() ?

output$report <- downloadHandler(

 params <- list(myPlot = p2)

)

1
  • 1
    @ismirsehregal, Sorry I did not unaccept your answer. I accepted both the two answer. I did not realize that if I accept second time another answer, the first accepted answer will automatically become unaccepted. Sorry I will change it back. Thank you very much for your help! Commented Feb 23, 2022 at 8:11

2 Answers 2

1

You can wrap the resulting plotly object in reactive or reactiveVal to pass it to the output and the downloadHandler:

library(shiny)
library(plotly)

writeLines(con = "report.Rmd", text = "---
title: 'Plotly report'
output: html_document
params:
  plotly_object: NA
---

```{r plotlyout, echo=FALSE, message=FALSE, out.width='100%'}
params$plotly_object
```")

ui = fluidPage(
  plotlyOutput("Plot"),
  downloadButton("report_button", "Generate report")
)

server = function(input, output, session) {
  irisPlot <- reactive({
    p <- ggplot(data=iris, aes(x = Sepal.Length, y = Sepal.Width)) +
      geom_point(aes(color=Species, shape=Species)) +
      labs(title = "Iris sepal width vs length")
    ggplotly(p)
  })

  output$Plot <- plotly::renderPlotly({
    irisPlot()
  })

  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(plotly_object = irisPlot())
      )
    }
  )
}

shinyApp(ui, server)

Another approach is using htmlwidgets::saveWidget (If you only need the html plot):

library(shiny)
library(plotly)

ui = fluidPage(
  plotlyOutput("Plot"),
  downloadButton("report_button", "Generate report") 
)

server = function(input, output, session) {
  irisPlot <- reactive({
    p <- ggplot(data=iris, aes(x = Sepal.Length, y = Sepal.Width)) +
      geom_point(aes(color=Species, shape=Species)) +
      labs(title = "Iris sepal width vs length")
    ggplotly(p)
  })
  
  output$Plot <- plotly::renderPlotly({
    irisPlot()
  })
  
  output$report_button <- downloadHandler(
    filename = "report.html",
    content = function(file) {
      htmlwidgets::saveWidget(widget = partial_bundle(irisPlot()), file = file, selfcontained = TRUE)
    }
  )
}

shinyApp(ui, server)
Sign up to request clarification or add additional context in comments.

Comments

1

Lets have files doc.Rmd:

---
title: "Untitled"
author: "danlooo"
date: "2/22/2022"
params:
  plot:
output: html_document
---

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

## Plot

```{r}
params$plot
```

And another file app.R in the same directory:

library(shiny)
library(plotly)
library(tidyverse)
library(rmarkdown)

ui <- fluidPage(
  plotlyOutput("plot"),
  downloadButton("download")
)

server <- function(input, output, session) {
  plot <- reactive({
    p <- ggplot(data = iris, aes(x = Sepal.Length, y = Sepal.Width)) +
      geom_point(aes(color = Species, shape = Species)) +
      labs(title = "Iris sepal width vs length")

    ggplotly(p)
  })

  output$plot <- renderPlotly(plot())

  output$download <- downloadHandler(
    filename = "report.html",
    content = function(file) {
      render(input = "doc.Rmd", output_dir = dirname(file), 
       output_file = basename(file), params = list(plot = plot()))
    }
  )
}


shinyApp(ui, server)

Then you can downlaod the report after clicking the button.

1 Comment

Thank you very much for your help. You answer is also very helpful, but I am so sorry that I can only accept one answer here. I want to tell you that I really appreciate your help.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.