【发布时间】:2021-11-25 05:45:13
【问题描述】:
我想使用 Shiny 应用程序中各个选项卡中的图表生成 R Markdown 报告。
只有在用户激活选项卡后,才会生成每个选项卡中的图。如果之前未激活选项卡,则该图将不存在,因此将无法用于报告。
因此,我尝试在调用 downloadHandler 之前使用 updateTabsetPanel 连续打开所有选项卡。然而,与手动单击选项卡相反,空选项卡会打开,并且文件下载对话框会在绘图开始渲染之前立即出现。只有保存报告文件后,Shiny 才会开始渲染绘图,报告为空。
有没有办法强制 downloadHandler 等到所有选项卡中的所有绘图完成渲染?
这是一个例子:
app.R
library(shiny)
library(ggplot2)
ui <- fluidPage(
mainPanel(
tabsetPanel(id = "tabs",
tabPanel("Plot1",
downloadButton("report", "create report"),
plotOutput("plot1")
),
tabPanel("Plot2", plotOutput("plot2")),
tabPanel("Plot3", plotOutput("plot3"))
)
)
)
server <- function(input, output, session) {
plots <<- list()
output$plot1 <- renderPlot({
plots[[1]] <<- ggplot(mtcars, aes(wt, mpg)) + geom_point()
plot(plots[[1]])
})
output$plot2 <- renderPlot({
plots[[2]] <<- ggplot(mtcars, aes(wt, cyl)) + geom_point()
plot(plots[[2]])
})
output$plot3 <- renderPlot({
plots[[3]] <<- ggplot(mtcars, aes(wt, disp)) + geom_point()
plot(plots[[3]])
})
output$report <- downloadHandler(
filename = ("report.html"),
content = function(file) {
updateTabsetPanel(session, "tabs", selected = "Plot1")
updateTabsetPanel(session, "tabs", selected = "Plot2")
updateTabsetPanel(session, "tabs", selected = "Plot3")
tempReport <- file.path(tempdir(), "report.rmd")
file.copy("report.rmd", tempReport, overwrite = TRUE)
params <- list(plots = plots)
rmarkdown::render(tempReport, output_file = file, params = params, envir = new.env(parent = globalenv()))
}
)
}
shinyApp(ui, server)
report.rmd
---
title: "report"
output: html_document
params:
plots: NA
---
```{r}
for (i in params$plots)
plot(i)
```
在这种情况下,为了简单起见,我将 tabPanel 调用放在了 downloadHandler 中。他们应该打开所有选项卡,以便渲染绘图,然后,rmarkdown 可以绘制它们。
如果单击“报告”按钮,将打开第 3 个选项卡,并且在呈现选项卡 2 和 3 的图之前出现文件对话框,因此报告仅包含图 1。但是如果您手动单击所有 3 个选项卡,然后单击“报告”,所有绘图都将被渲染并包含在报告中。
【问题讨论】:
-
欢迎来到 SO,Houndmux!大多数关于 SO(特别是 r 标签)的问题都受益于或确实需要可重现,以包括示例数据、最少代码和预期输出。请参阅stackoverflow.com/q/5963269、minimal reproducible example 和stackoverflow.com/tags/r/info,了解如何在这种情况下很好地提出问题。谢谢!
-
一种方法可能是使用
shinyjs包禁用下载按钮,仅在您需要的条件下启用它。 -
这仍然需要用户手动打开所有选项卡,以便首先渲染所有绘图。如果标签是自动打开的,我会更喜欢。但是在所有选项卡上连续使用 updateTabsetPanel 甚至不会实际呈现所有选项卡。它只呈现最后一个,即使在所有 updateTabsetPanel 调用之后调用的 downloadHandler 之后也是如此。所以没有给出执行顺序。
-
好的,我知道这不仅仅是在所有情节完成之前禁用
downloadHandler。请制作一个可重复的小例子来清楚地证明这一点。请不要包含与基本流程无关的小部件、控件或代码;我们不需要花哨的情节,只需plot(1);plot(2);plot(3);就足够了。祝你好运! -
添加了一个例子。我将 ggplots 保存在“绘图”列表中而不是在 rmd 文件中重新定义绘图的原因是,在我的实际应用程序中,绘图需要很多不同的数据,我不想转移到 rmd文件。这些也是交互式 ggplotly 对象,用户可以在其中选择图中的数据,我希望这些选择包含在报告中。