Export R Shiny Page to PDF

旧城冷巷雨未停 提交于 2020-07-28 06:03:05

问题


I have a large Shiny application that has a number of prompts, then generates tables and plot based on those inputs. I don't use rmarkdown or knitr or anything to format the output. I just use the standard Shiny elements (sidebarPanel, mainPanel, etc.). For the plots and tables I use the standard reactive renderPlot and renderTable objects. I'm looking for an easy way to have a button called "Export to PDF" that exports the elements on the page to a PDF document.

I've looked into using knitr and rmarkdown to generate a document with some fancy formatting (see here and here for examples). The problem is that it appears that I'll need to regenerate the tables and plots either within the Rmd file or the server.R within a downloadHandler object, and I'd like to avoid that.

Is there any way to output the page as a pdf more easily. More specifically, is there any way to directly reference the output tables and plots (i.e. the output$ objects) from within the Rmd file so that plots and tables don't need to be generated twice.

Edit: Here is some simplified code. Note getDataset() is a reactive function that queries a database based on the inputs. My goal is to simply add an "Export" button that exports the already-generated plots and table. (Also as a side note, is there any way I can get a reactive dataset that is shared among all reactive elements? i.e. not need to have ds <- getDataset() in every object?)

Server

output$hist <- renderPlot({
  ds <- getDataset()
  # do data transformations

  ggplot(ds, aes(val)) +
    geom_histogram(binwidth = binSize, aes(fill = ..count..)) +
    labs(title = "val dist", x = "val", y = "Count") + 
    scale_fill_gradient("Count", low = "green", high = "red", guide = FALSE) +
    scale_x_continuous(limits = c(min(ds$val), quantile(ds$val, 0.99))) +
    geom_hline(yintercept=maxY, linetype=3)
})

output$time <- renderPlot({
  ds <- getDataset()
  # do data transformations
  ggplot(ds, aes(as.POSIXlt(unixTime, origin="1970-01-01", tz="UTC"), val), colour = val) +
    scale_y_continuous(limits = c(min(ds$val), quantile(ds$val, 0.99))) +
    labs(title = "Val Over Time", x = "Time (UTC)", y = "val (ms)") +
    geom_point(alpha = 0.3, size = 0.7) +
    geom_smooth()
})
output$stats <- renderTable({
  statsDf = getDataset()
  # do data transformations
  statsDf
})

UI

ui <- fluidPage(
  titlePanel("Results"),

  sidebarLayout(
    sidebarPanel(
      dateInput("startDateTime", "Start Date:", value = "2016-10-21"),
      textInput("startTime", "Start Time", "00:00:00"),
      br(),
      dateInput("endDateTime", "End Date:", value = "2016-10-21"),
      textInput("endTime", "End Time", value = "02:00:00"),
      br(),
      submitButton("Submit")
    ),
    mainPanel(
      tabsetPanel(type = "tabs",
                  tabPanel("Plots",
                           plotOutput("hist"),
                           plotOutput("time"),
                  tabPanel("Statistics", tableOutput("stats"))
      )
    )
  )
)

回答1:


First of all , you should really produce a reproducible example not just a sample of your code. We should copy and paste your code and it will run.

The idea

  1. Since you are using ggplot2 which is king of grid plots, I think one easy option to save plots/tables is to use gridExtra package. Using grid.arrange or arrangeGrobs you can save your grobs to predefined device. Then, downloadhandler will do the download.

  2. To not regenerate all the plots each time, I think one solution is to save them in a global variable that you update each time you change the plot. Here reactiveValues come in rescue to store plots and tables ad dynamic variable.

Solution

ui.R

library(shiny)

shinyUI(fluidPage(

  # Application title
  titlePanel("Save ggplot plot/table without regenration"),

  # Sidebar with a slider input for number of bins
  sidebarLayout(
    sidebarPanel(
      downloadButton('export')
    ),

    # Show a plot of the generated distribution
    mainPanel(
      plotOutput("p1"),
      plotOutput("p2"),
      tableOutput("t1")
    )
  )
))

server.R

library(shiny)
library(ggplot2)
library(gridExtra)

shinyServer(function(input, output) {
  ## vals will contain all plot and table grobs
  vals <- reactiveValues(p1=NULL,p2=NULL,t1=NULL)

  ## Note that we store the plot grob before returning it 
  output$p1 <- renderPlot({
    vals$p1 <- qplot(speed, dist, data = cars)
    vals$p1
  })

  output$p2 <- renderPlot({
    vals$p2 <- qplot(mpg, wt, data = mtcars, colour = cyl)
    vals$p2
  })
  ## same thing for th etable grob
  output$t1 <- renderTable({
    dx <- head(mtcars)
    vals$t1 <- tableGrob(dx)
    dx
  })
  ## clicking on the export button will generate a pdf file 
  ## containing all grobs
  output$export = downloadHandler(
    filename = function() {"plots.pdf"},
    content = function(file) {
     pdf(file, onefile = TRUE)
     grid.arrange(vals$p1,vals$p2,vals$t1) 
     dev.off()
    }
  )
})


来源:https://stackoverflow.com/questions/40272489/export-r-shiny-page-to-pdf

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!