如何将Shiny应用程序中的表格和绘图作为参数传递给R Markdown?

shi*_*iny 5 r r-markdown shiny reactive

在此 Shiny 应用程序中,用户可以上传 .csv 文件,以表格和绘图的形式获取结果。我希望能够将结果下载为 PDF 文档。

输入文件

#I created the input .csv file to be used in the app from diamonds data.frame
library(ggplot2)
df <-  diamonds[1:5000, ]
head(df)
write.csv(df, "df.csv")
Run Code Online (Sandbox Code Playgroud)

应用程序

library(tidyverse)
library(shiny)
library(rmarkdown)
library(knitr)

ui <- fluidPage(
  sidebarLayout(
    sidebarPanel(fileInput("file","Upload your file"), 
                 width =2),
    mainPanel(
      width = 10,
      downloadButton("report", "Download report"),
      tableOutput("table"),
      tags$br(),
      tags$hr(),
      plotOutput("plot1"), 
      tags$br(),
      tags$hr(),
      plotOutput("plot2")
    )
  )
)

server <- function(input,output){

  data <- reactive({
    file1 <- input$file
    if(is.null(file1)){return()} 
    read.csv(file1$datapath, header=TRUE, sep=',')
    })


  output$table <- renderTable({
    if (is.null(data())) { return() }

      df <- data() %>% 
      dplyr::select(cut, color, price) %>% 
      dplyr::group_by(cut, color) %>% 
      dplyr::summarise_all(funs(min(.), mean(.), median(.),max(.),sd(.), n() ))  
  })  

  table_rmd <- reactive({
    df <- data() %>% 
      dplyr::select(cut, color, price) %>% 
      dplyr::group_by(cut, color) %>% 
      dplyr::summarise_all(funs(min(.), mean(.), median(.),max(.),sd(.), n() )) 
  })

  output$plot1 <- renderPlot({
    if (is.null(data())) { return() }

    ggplot(data(), aes (x =carat, y = price, col = color))+
      geom_point()+
      facet_wrap(~cut)
    }
  )

  plot_rmd <- reactive({
   chart <- ggplot(data(), aes (x =carat, y = price, col = color))+
      geom_point()+
      facet_wrap(~cut)
   chart
  }
  )

    #https://shiny.rstudio.com/articles/generating-reports.html
    output$report <- downloadHandler(
      filename = "report.pdf",
      content = function(file) {
        tempReport <- file.path(tempdir(), "report.Rmd")
        file.copy("report.Rmd", tempReport, overwrite = TRUE)

        params <- list(table1 = table_rmd(),
                       plot1 = plot_rmd())

        rmarkdown::render(tempReport, output_file = file,
                          params = params,
                          envir = new.env(parent = globalenv())
        )
      }
    )
}  


shinyApp(ui=ui, server = server)
Run Code Online (Sandbox Code Playgroud)

报告.Rmd

---
title: "Dynamic report"
output: pdf_document

params:
  table1: NA
  plot1: NA

---


This is the firs plot 

```{r}
params$plot1
```

This is the first table

```{r}
kable(params$table1)
```
Run Code Online (Sandbox Code Playgroud)

我尝试了不同的方法将表格和绘图从 Shiny 作为参数传递给 R Markdown,但没有成功。

我将非常感谢您解决此问题的建议。

更新

我已经尝试过 @BigDataScientist 的答案,但收到此错误

“C:/ Program Files / RStudio / bin / pandoc / pandoc”+ RTS -K512m -RTS report.utf8.md --to Latex --from markdown + autolink_bare_uris + ascii_identifiers + tex_math_single_backslash --output pandoc20e043232760.tex --template “ C:\PROGRA~1\R\R-35~1.2\library\RMARKD~1\rmd\latex\DEFAUL~3.TEX" --highlight-style tango --pdf-engine pdflatex --variablegraphics=yes - -变量“geometry:margin = 1in”--variable“compact-title:yes”警告:错误:无法编译C:\ Users \ user \ AppData \ Local \ Temp \ RtmpYvWn8M \ file20e042326267.tex。请参阅https://yihui.name/tinytex/r/#debugging了解调试技巧。[没有可用的堆栈跟踪]

这里是sessionInfo()

> sessionInfo()
R version 3.5.2 (2018-12-20)
Platform: x86_64-w64-mingw32/x64 (64-bit)
Running under: Windows 7 x64 (build 7601) Service Pack 1

Matrix products: default

locale:
[1] LC_COLLATE=English_New Zealand.1252  LC_CTYPE=English_New Zealand.1252    LC_MONETARY=English_New Zealand.1252 LC_NUMERIC=C                        
[5] LC_TIME=English_New Zealand.1252    

attached base packages:
[1] stats     graphics  grDevices utils     datasets  methods   base     

other attached packages:
 [1] bindrcpp_0.2.2  forcats_0.3.0   stringr_1.4.0   dplyr_0.7.8     purrr_0.2.5     readr_1.3.1     tidyr_0.8.2     tibble_2.0.1    tidyverse_1.2.1 ggplot2_3.1.0  
[11] shiny_1.2.0    

loaded via a namespace (and not attached):
 [1] tinytex_0.15.2   tidyselect_0.2.5 xfun_0.9         haven_2.0.0      lattice_0.20-38  colorspace_1.4-0 generics_0.0.2   htmltools_0.3.6  yaml_2.2.0      
[10] utf8_1.1.4       rlang_0.4.0      later_0.8.0      pillar_1.3.1     glue_1.3.0       withr_2.1.2      readxl_1.2.0     modelr_0.1.2     bindr_0.1.1     
[19] plyr_1.8.4       cellranger_1.1.0 munsell_0.5.0    gtable_0.2.0     rvest_0.3.2      evaluate_0.12    labeling_0.3     knitr_1.21       httpuv_1.4.5.1  
[28] fansi_0.4.0      broom_0.5.1      Rcpp_1.0.0       xtable_1.8-3     promises_1.0.1   scales_1.0.0     backports_1.1.3  jsonlite_1.6     mime_0.6        
[37] hms_0.4.2        digest_0.6.18    stringi_1.2.4    grid_3.5.2       cli_1.0.1        tools_3.5.2      magrittr_1.5     lazyeval_0.2.1   crayon_1.3.4    
[46] pkgconfig_2.0.2  xml2_1.2.0       rsconnect_0.8.13 lubridate_1.7.4  assertthat_0.2.0 rmarkdown_1.11   httr_1.4.0       rstudioapi_0.9.0 R6_2.3.0        
[55] nlme_3.1-137     compiler_3.5.2 
Run Code Online (Sandbox Code Playgroud)

teo*_*fil 5

您可以将 R 对象作为params列表的一部分传递给参数化的Rmd. 这是常规交互会话中的示例(无 Shiny)。report.Rmd与问题中的相同。由某些脚本生成df并在您的环境中可用。然后你可以将它们包装起来并将它们传递给.plRlistparamsrender

library(rmarkdown)
library(ggplot2)

df <- head(iris)
pl <- ggplot(iris, aes(x = Sepal.Width)) + geom_histogram(color = "white")

render(
  input = "report.Rmd",
  params = list("table1" = df, "plot1" = pl),
  output_file = "rendered-from-session.pdf"
)

Run Code Online (Sandbox Code Playgroud)

的屏幕截图rendered-from-session.pdf

在此输入图像描述

这是否是一个好的策略是另一个问题。app如果制作表格和绘图的代码与和相同Rmd,那么最好将其放在由app和来源的单独脚本中Rmd。这样,当您想要更改表格/绘图代码时,您只需编辑一个文档。在这种情况下,您可以将参数传递给绘图函数而不是绘图本身。这样做的缺点是,如果您有许多不同的图,需要跟踪许多不同的参数。或者,如果计算/绘图需要很长时间,那么您不想重复两次。

回到你的闪亮应用程序。事实上,您的应用程序代码也适用于我,就像通过 Shiny 一样。我可以制作pdf(即使table_rmd()reactive没有明确返回df)。所以很可能是 pandoc 或 Latex 没有弄清楚临时文件/文件夹在哪里的问题。由于您仍在测试,我会尝试保存到已知位置而不是临时目录,以查看这是否不是某种权限问题。

您可以像这样修改您的处理程序。删除对 的调用并提供对tempdir的完整路径。您还可以尝试给出 的完整路径。第一种情况应该可以正常工作。在第二种情况下(而不是传递给),浏览器可能会给您一个错误,但 pdf 仍应使用您提供的文件名在后台呈现。report.Rmdrenderoutput_file"PATH/TO/OUTPUT"fileoutput_filedownload

  output$report <- downloadHandler(
    filename = "report.pdf",
    content = function(file) {
      # tempReport <- file.path(tempdir(), "report.Rmd")
      # file.copy("report.Rmd", tempReport, overwrite = TRUE)

      params <- list(table1 = table_rmd(),
                     plot1 = plot_rmd())

      rmarkdown::render(input = "PATH/TO/report.Rmd", 
                        output_file = file,
                        params = params,
                        envir = new.env(parent = globalenv())
      )
    }
  )
Run Code Online (Sandbox Code Playgroud)

这至少可以确认您的代码正在运行,除了这些tempdir()东西。如果您有选择,请在 Linux 计算机或 Mac 上尝试您的应用程序。