4

I would like to download Report within Shiny App, which includes Plotly graph. So far i have not found any answer on stackoverflow. Till this moment im able to download the screenshot of Plotly but it appears only in my working directory and it is not sent to Rmarkdown.

Example code:

library(shiny)
library(plotly)
library(rsvg)
library(ggplot2)

d <- data.frame(X1=rnorm(50,mean=50,sd=10),X2=rnorm(50,mean=5,sd=1.5),Y=rnorm(50,mean=200,sd=25))

ui <-fluidPage(
  title = 'Download report',
  sidebarLayout(

    sidebarPanel(
      helpText(),
      radioButtons('format', 'Document format', c('PDF', 'HTML', 'Word'),
                   inline = TRUE),
      downloadButton('downloadReport'),
      tags$script('
                  document.getElementById("downloadReport").onclick = function() {
                  var plotly_svg = Plotly.Snapshot.toSVG(
                  document.querySelectorAll(".plotly")[0]
                  );

                  Shiny.onInputChange("plotly_svg", plotly_svg);
                  };
                  ')
      ),
    mainPanel(
      plotlyOutput('regPlot')
    )
      )
)

server <- function(input, output, session) {

  output$regPlot <- renderPlotly({
    p <- plot_ly(d, x = d$X1, y = d$X2,mode = "markers")
    p
  })

  observeEvent(input$plotly_svg, priority = 10, {
    png_gadget <- tempfile(fileext = ".png")
    png_gadget <- "out.png"
    print(png_gadget)
    rsvg_png(charToRaw(input$plotly_svg), png_gadget)
  })

  output$downloadReport <- downloadHandler(
    filename = function() {
      paste('my-report', sep = '.', switch(
        input$format, PDF = 'pdf', HTML = 'html', Word = 'docx'
      ))
    },

    content = function(file) {
      src <- normalizePath('testreport.Rmd')

      owd <- setwd(tempdir())
      on.exit(setwd(owd))
      file.copy(src, 'testreport.Rmd')

      library(rmarkdown)
      out <- render('testreport.Rmd', params = list(region = "Test"), switch(
        input$format,
        PDF = pdf_document(), HTML = html_document(), Word = word_document()
      ))
      file.rename(out, file)
    }
  )
}

shinyApp(ui = ui, server = server)

and testreport.Rmd file:

---
title: "test"
output: pdf_document
params:
  name: "Test"
  region: 'NULL'
---

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

Any help would be appreciated, because there is not many sources and documentations about R Plotly.

Cheers

Mal_a
  • 3,670
  • 1
  • 27
  • 60
  • Do you want to plot inside Rmd with ploty? Or so you want to download something into an Rmd? I am confused by "Till this moment im able to download the screenshot of Plotly but it appears only in my working directory and it is not sent to Rmarkdown" – llrs Dec 14 '16 at 11:13
  • I would like to have plotly screenshot from shiny app inside of the report file (rmarkdown) – Mal_a Dec 14 '16 at 11:36
  • I don't know how plotly works but once you have the image why can't you use this [solution](http://stackoverflow.com/a/25167279/2886003)? Or by screenshot you mean the code used to generate such images? In the later case has you tired to include the code in a chunk? – llrs Dec 14 '16 at 11:50
  • well if i knew how to do it, definatelly i would not post it on stackoverflow...what i would appreciate is a full answer with a code – Mal_a Dec 14 '16 at 12:16
  • I don't think you answered my questions, which would help me to understand your problem to create an answer for you. Maybe they aren't clear enough, case let me know . – llrs Dec 14 '16 at 12:31
  • I am looking for the solution which will pass the picture of plotly dynamically as an object to rmarkdown, rather the save it in the working directory and then subsequently read into rmarkdown. with `ggplot` it is very easy solution as you pass an object (parameter) to rmarkdown and its automatically there(http://rmarkdown.rstudio.com/developer_parameterized_reports.html) – Mal_a Dec 14 '16 at 12:57
  • 2
    your markdown file has no `out.png`, where do you expect the plot to be? Also, you can when a plotly is included in an markdown, it is converted to png automatically for certain formats. I can make an example with a dynamic plot if needed. – NicE Dec 14 '16 at 13:32
  • I think that is what the OP wants @NicE. I recommend to have your code generating the image in a code chunk Malvina. – llrs Dec 14 '16 at 14:16
  • @NicE i was not sure how i can pass the `out.png` from shiny app to rmarkdown. The sample code would be great – Mal_a Dec 14 '16 at 14:40

2 Answers2

1

If out.png is downloaded to your working directory, you can modify the content function of your downloadHandler to move it to the temporary directory and add it to the report:

content = function(file) {
      temp_dir <- tempdir()
      tempReport <- file.path(temp_dir, 'testreport.Rmd')
      tempImage <- file.path(temp_dir, 'out.png')
      file.copy('testreport.Rmd', tempReport, overwrite = TRUE)
      file.copy('out.png', tempImage, overwrite = TRUE)

      library(rmarkdown)
      out <- render(tempReport, params = list(region = "Test"), switch(
        input$format,
        PDF = pdf_document(), HTML = html_document(), Word = word_document()
      ))
      file.rename(out, file)
    }

Your testreport.Rmd could look like (more info here):

---
title: "test"
---

Here's the plot image.

![Plot image](out.png)

You could also pass the arguments of your plotly function in the render of your content function as explained here and use a parametrized Rmarkdown file but this only works for Html reports.

Community
  • 1
  • 1
NicE
  • 21,165
  • 3
  • 51
  • 68
  • Thats interesting approach, however if i zoom the `plotly` plot in the shiny app, the report shows only the primary plot (no zoom)..I would like to mirror all the actions which has been made in shiy `plotly`..What wonders me actually that the image `out.png` which appears in my working directory, its properly zoomed and respond to all the actions taken in shiny `plotly` plot... – Mal_a Dec 16 '16 at 08:28
  • 1
    Good point, the directory was not switching back to the initial working directory so it was just recopying the file in the temp directory, I changed the `content` code, should work fine now. – NicE Dec 16 '16 at 09:30
  • Great!!Thanks!! It is working perfectly!! It was quite of a trouble with `plotly` – Mal_a Dec 16 '16 at 09:32
0

Depending on how deep you want to dive into this, I would suggest creating a .brew file with your shiny code and than you can have your user send the information to the brew file and create the plot. This would give you a static code file which is updated dynamically with new data, each time. The only draw back is that when you make changes to shiny you have to make the same changes to your brew file. The other option is to create a flex dashboard with rmarkdown using the new RStudio 1.0 which becomes a html file. See (Create parametric R markdown documentation?) for brew example.

Community
  • 1
  • 1
Akbar
  • 130
  • 8