How to make pdf download in shiny app response to user inputs?

后端 未结 1 444
说谎
说谎 2020-12-14 13:19

I want to make the table and the barplot generated by my shiny app to be downloadable as a pdf report. I can generate the report with the selected inputs the first time I st

相关标签:
1条回答
  • 2020-12-14 13:58

    I apologize that it took me this long to get back to this. After looking at what I've done, it turns out it was a little more involved than I remembered.

    Here's my example app code

    library(shiny)
    library(ggplot2)
    library(magrittr)
    
    ui <- shinyUI(
      fluidPage(
        column(
          width = 2,
          selectInput(
            inputId = "x_var",
            label = "Select the X-variable",
            choices = names(mtcars)
          ),
          selectInput(
            inputId = "y_var",
            label = "Select the Y-variable",
            choices = names(mtcars)
          ),
          selectInput(
            inputId = "plot_type",
            label = "Select the plot type",
            choices = c("scatter plot", "boxplot")
          ),
          downloadButton(
            outputId = "downloader",
            label = "Download PDF"
          )
        ),
        column(
          width = 3,
          tableOutput("table")
        ),
        column(
          width = 7,
          plotOutput("plot")
        )
      )
    )
    
    server <- shinyServer(function(input, output, session){
    
      #****************************************
      #* Reactive Values
    
      table <- reactive({
        mtcars[, c(input[["x_var"]], input[["y_var"]])]
      })
    
      plot <- reactive({
        p <- ggplot(data = mtcars,
                    mapping = aes_string(x = input[["x_var"]],
                                         y = input[["y_var"]]))
        if (input[["plot_type"]] == "scatter plot")
        {
          p + geom_point()
        }
        else
        {
          p + geom_boxplot()
        }
      })
    
      #****************************************
      #* Output Components
    
      output$table <- 
        renderTable({
          table()
        })
    
      output$plot <- 
        renderPlot({
          plot()
        })
    
      #****************************************
      #* Download Handlers
    
      output$downloader <- 
        downloadHandler(
          "results_from_shiny.pdf",
          content = 
            function(file)
            {
              rmarkdown::render(
                input = "report_file.Rmd",
                output_file = "built_report.pdf",
                params = list(table = table(),
                              plot = plot())
              ) 
              readBin(con = "built_report.pdf", 
                      what = "raw",
                      n = file.info("built_report.pdf")[, "size"]) %>%
                writeBin(con = file)
            }
        )
    })
    
    shinyApp(ui, server)
    

    And here is my RMD (entitled report_file.Rmd)

    ---
    title: "Parameterized Report for Shiny"
    output: pdf_document
    params:
      table: 'NULL'
      plot: 'NULL'
    ---
    
    ```{r}
    params[["plot"]]
    ```
    
    ```{r}
    params[["table"]]
    ```
    

    Some highlights to look for

    • Notice the exists of params in the YAML front matter of the RMarkdown script. This allows us to pass in a list of values to be used in the script when we invoke rmarkdown::render(..., params = list(...))
    • I always build my PDF to a dummy file. That way it's easy to find.
    • The reason I always build to a dummy file is that to get the download handler to work, you need to read the bit-content of the PDF and push it to the file argument using writeBin. See my downloadHandler construction.
    • Using the parameterized report means you don't have to recreate your outputs in the rmarkdown script. The work was done in the Shiny app, the parameterized report just helps you send the objects correctly. It isn't quite the same as passing files back and forth (although if it could be that easy, I'd love to know it).

    Read more about parameterized reports here: http://rmarkdown.rstudio.com/developer_parameterized_reports.html

    0 讨论(0)
提交回复
热议问题