【问题标题】:Export R Shiny Page to PDF将 R Shiny Page 导出为 PDF
【发布时间】:2017-03-09 10:08:22
【问题描述】:

我有一个大型 Shiny 应用程序,它有许多提示,然后根据这些输入生成表格和绘图。我不使用 rmarkdown 或 knitr 或任何东西来格式化输出。我只使用标准的 Shiny 元素(sidebarPanel、mainPanel 等)。对于绘图和表格,我使用标准的反应式 renderPlot 和 renderTable 对象。 我正在寻找一种简单的方法来创建一个名为“导出为 PDF”的按钮,该按钮将页面上的元素导出为 PDF 文档。

我已经研究过使用 knitr 和 rmarkdown 来生成具有一些花哨格式的文档(参见 herehere 示例)。 问题是我似乎需要在 Rmd 文件或 downloadHandler 对象中的 server.R 中重新生成表格和绘图,我想避免这种情况。

有什么方法可以更轻松地将页面输出为 pdf。更具体地说,有什么方法可以直接从 Rmd 文件中引用输出表和绘图(即 output$ 对象),这样就不需要生成两次绘图和表。

编辑:这是一些简化的代码。注意 getDataset() 是一个响应式函数,它根据输入查询数据库。 我的目标是简单地添加一个“导出”按钮来导出已经生成的绘图和表格。 (另外作为旁注,有什么方法可以获得在所有反应元素之间共享的反应数据集?即不需要在每个对象中都有 ds

服务器

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 <- 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"))
      )
    )
  )
)

【问题讨论】:

  • 我正在使用 ggplot。我将编辑帖子并放入一些示例代码

标签: r shiny knitr r-markdown


【解决方案1】:

首先,您应该真正生成一个可重现的示例,而不仅仅是您的代码示例。我们应该复制并粘贴您的代码,它就会运行。

想法

    1234563使用 grid.arrangearrangeGrobs 您可以将您的 grobs 保存到预定义的设备。然后,downloadhandler 将进行下载。
  1. 为了不每次都重新生成所有绘图,我认为一种解决方案是将它们保存在每次更改绘图时更新的全局变量中。这里reactiveValues 来救援存储图表和表格广告动态变量。

解决方案

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")
    )
  )
))

服务器.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()
    }
  )
})

【讨论】:

  • 啊,很聪明。所以我认为没有办法在不需要重新生成图的情况下使用 r markdown?这很不幸,但您的想法非常适合快速修复!抱歉没有包含实际代码。我确信通过将完整代码发布到公共网站会违反许多 NDA。无论如何,我只是在寻找一般策略。谢谢!
  • @agstudy:我使用plotly 绘图和datatable 用于表格。我无法对这些元素使用类似的东西。我收到一个错误"Error in gList: only 'grobs' allowed in "gList"。有没有办法可以将plotlydatatable 元素转换为grobs
  • @krish 抱歉,我不知道。我不使用情节。
  • @krish 你有没有用 plotly 和 DT 来做这个?
  • @DanteSmith 你呢?
猜你喜欢
  • 2020-07-09
  • 1970-01-01
  • 1970-01-01
  • 2021-07-27
  • 2020-10-28
  • 2018-09-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多