r-将数据帧作为参数从Shiny应用程序传递到RMarkdown



我仍在为我正在开发的Shiny应用程序的某些方面而挣扎。目的是用户上传一个csv数据文件,然后对其进行处理以生成报告(从.Rmd模板(,然后用户可以将其下载为可编辑的Word.doc.

如果我在正常的R会话中渲染.Rmd,它可以正常工作。然而,如果从我的Shiny应用程序中完成,我会得到以下错误:


Warning: Error in unique: object 'report.data' not found
[No stack trace available]

report.data应该是通过读取输入.csv文件生成的数据帧。令人困惑的是,该应用程序有时确实有效(我认为如果report.data已经在全球环境中可用,就会出现这种情况。(。

我已经尝试在.Rmd文件的标题中定义params(请参阅下面注释的行。(-如果我这样做,那么代码运行时不会出现错误,但生成的word文档除了标题外都是空白的。

有人看到我哪里错了吗?一如既往地感谢您花时间阅读并回复。

很抱歉,我觉得我在Shiny中做了很多看似很基本的事情来寻求帮助,但我确实在寻找类似的问题,但从来没有找到完全正确的东西!但一旦我有了这些基本的东西,我就可以自己进步了。

生成报表数据示例输入.csv文件的代码:

library(dplyr)
set.seed(1234)
product1.parameter1.location1 <- data.frame(
result = rnorm(25, mean = 2.5, sd = 0.2), 
product = c("Red Aeroplanes"), 
parameter = c("Parameter 1"), 
sample.no = c(1:25), 
location = c("Factory 1")
)
product1.parameter1.location2 <- data.frame(
result = rnorm(25, mean = 2.6, sd = 0.1), 
product = c("Red Aeroplanes"), 
parameter = c("Parameter 1"), 
sample.no = c(1:25), 
location = c("Factory 2")
)
product1 <- rbind(product1.parameter1.location1, product1.parameter1.location2)
product2.parameter1.location1 <- data.frame(
result = rnorm(25, mean = 10, sd = 2), 
product = c("Blue Trollies"), 
parameter = c("Parameter 1"), 
sample.no = c(1:25), 
location = c("Factory 1")
)
product2.parameter1.location2 <- data.frame(
result = rnorm(25, mean = 9.5, sd = 0.75), 
product = c("Blue Trollies"), 
parameter = c("Parameter 1"), 
sample.no = c(1:25), 
location = c("Factory 2"))
product2.parameter1 <- rbind(product2.parameter1.location1, product2.parameter1.location2)
product2.parameter2.location1 <- data.frame(
result = rnorm(25, mean = 30, sd = 1.8), 
product = c("Blue Trollies"), 
parameter = c("Parameter 2"), 
sample.no = c(1:25), 
location = c("Factory 1")
)
product2.parameter2.location2 <- data.frame(
result = rnorm(25, mean = 25, sd = 0.75), 
product = c("Blue Trollies"), 
parameter = c("Parameter 2"), 
sample.no = c(1:25), 
location = c("Factory 2"))
product2.parameter2 <- rbind(product2.parameter2.location1, product2.parameter2.location2)
product2 <- rbind(product2.parameter1, product2.parameter2)
product3.parameter1.location1 <- data.frame(
result = rnorm(35, mean = 2, sd = 0.2), 
product = c("Brown Carriages"), 
parameter = c("Parameter 1"), 
sample.no = c(1:35), 
location = c("Factory 1")
)
product3.parameter1.location2 <- data.frame(
result = rnorm(35, mean = 1.9, sd = 0.15), 
product = c("Brown Carriages"), 
parameter = c("Parameter 1"), 
sample.no = c(1:35), 
location = c("Factory 2"))
product3.parameter1 <- rbind(product3.parameter1.location1, product3.parameter1.location2)
product3.parameter2.location1 <- data.frame(
result = rnorm(35, mean = 4, sd = 0.4), 
product = c("Brown Carriages"), 
parameter = c("Parameter 2"), 
sample.no = c(1:35), 
location = c("Factory 1")
)
product3.parameter2.location2 <- data.frame(
result = rnorm(35, mean = 3.8, sd = 0.5), 
product = c("Brown Carriages"), 
parameter = c("Parameter 2"), 
sample.no = c(1:35), 
location = c("Factory 2"))
product3.parameter2 <- rbind(product3.parameter2.location1, product3.parameter2.location2)
product3.parameter3.location1 <- data.frame(
result = rnorm(35, mean = 10, sd = 1.8), 
product = c("Brown Carriages"), 
parameter = c("Parameter 3"), 
sample.no = c(1:35), 
location = c("Factory 1")
)
product3.parameter3.location2 <- data.frame(
result = rnorm(35, mean = 10, sd = 2), 
product = c("Brown Carriages"), 
parameter = c("Parameter 3"), 
sample.no = c(1:35), 
location = c("Factory 2"))
product3.parameter3 <- rbind(product3.parameter3.location1, product3.parameter3.location2)
product3 <- rbind(product3.parameter1, product3.parameter2, product3.parameter3)
write.csv(product1, "product1.csv", row.names = FALSE)
write.csv(product2, "product2.csv", row.names = FALSE)
write.csv(product3, "product3.csv", row.names = FALSE)
report.data <- rbind(product1, product2, product3) %>% mutate(identifier = paste(product, parameter, sep = " ")) 
write.csv(report.data, "all.data.csv", row.names = FALSE)

应用程序。R代码:

#
# This is a Shiny web application. You can run the application by clicking
# the 'Run App' button above.
#
# Find out more about building applications with Shiny here:
#
#    http://shiny.rstudio.com/
#
library(shiny)
# Define UI for application that draws a histogram
ui <- fluidPage(
# Application title
titlePanel("R Shiny app"),
# Sidebar with file input
sidebarLayout(
sidebarPanel(
fileInput(
inputId = "file1",
label = "Select file(s)",
multiple = TRUE,
accept = NULL,
width = NULL,
buttonLabel = "Browse...",
placeholder = "No file(s) selected"
),
downloadButton("report", "Generate report")
),
# Show a plot of the generated distribution
mainPanel(
plotOutput("distPlot")
)
)
)
# Define server logic required to draw a histogram
server <- function(input, output) {

output$report <- downloadHandler(
reactive(file <- input$file1),
# For PDF output, change this to "report.pdf"
filename = "report.doc",
content = function(file) {
# Copy the report file to a temporary directory before processing it, in
# case we don't have write permissions to the current working dir (which
# can happen when deployed).
tempReport <- file.path(tempdir(), "wordreport.Rmd")
file.copy("wordreport.Rmd", tempReport, overwrite = TRUE)
# Knit the document, passing in the `params` list, and eval it in a
# child of the global environment (this isolates the code in the document
# from the code in this app).
params <- list(report.data = input$file1)
rmarkdown::render(tempReport, output_file = "wordreport.doc",
params = params,
envir = new.env(parent = globalenv()))
file.copy("wordreport.doc", file)
}
)
}
# Run the application 
shinyApp(ui = ui, server = server)

.Rmd文件(注释掉了与params声明相关的行(:

---
title: "Comparison Report  for [CATEGORY] in [MONTH/YEAR]"
output: word_document
toc: yes
#params:
#report.data: report.data
---
```{r setup, include=FALSE, comment = "", results = 'asis', echo = FALSE}
library(dplyr)
library(ggplot2)
library(purrr)
knitr::opts_chunk$set(echo = FALSE)
```
#report.data <- params$report.data
```
my_plot <- function(df) {
ggplot(df, aes(x = sample.no, y = result)) +
geom_point(aes(colour = location)) +
geom_hline(aes(yintercept = mean(result)), colour = "black", linetype = "dotted") +
geom_hline(aes(yintercept = mean(result) + 1.96 * sd(result)), colour = "red", linetype = "dashed") +
geom_hline(aes(yintercept = mean(result) - 1.96 * sd(result)), colour = "red", linetype = "dashed") +
theme_classic() +
theme(legend.title = element_blank()) +
labs(
title = paste0("Comparison for ", unique(df$identifier)),
x = "Sample number",
y = "Result") +
#caption = paste0("Caption here.")) +
expand_limits(y = 0) +
coord_cartesian(xlim = c(0, max(df$sample.no) + 2)) +    
theme(
plot.caption=element_text(size=12, hjust = 0, margin = margin(t=20)),
plot.margin = margin(b=50)
)
}
```
```{r, comment = "", results = 'asis', echo = FALSE}
purrr::map(unique(report.data$identifier),
function(x) {
#section heading
cat("#", (x), "n")
cat("nn")
# filter data before passing it to the plot function
report.data %>% 
dplyr::filter(identifier == x) %>%
my_plot() %>% print()
cat("nn")
no.outofbounds <- report.data %>% 
dplyr::filter(identifier == x) %>%
mutate(outofbounds = ifelse(result > mean(result)+1.96*sd(result)|result < mean(result)-1.96*sd(result), TRUE, FALSE)) %>% 
dplyr::filter(outofbounds == TRUE) %>% 
nrow()
ifelse(no.outofbounds > 0, paste(cat(no.outofbounds), " results greater than 1.96 standard deviations away from the mean."), "All results within 1.96 standard deviations of the mean.") %>% 
cat()
cat("nn")
CV <- report.data %>% 
dplyr::filter(identifier == x) %>%
summarise(CV = sd(result)/mean(result) * 100) %>% 
round(2)
cat("nn")
paste("The all-site/factor CV for this parameter is ", CV, "%.") %>% 
cat()
cat("nn")
cat("APPROVED/REJECTED.")
cat("nn")

}
) -> results
```

您的代码有几个问题。我会逐一检查

downloadHandler((中的参数无效

您正在将reactive类的对象传递给downloadHandler()contentType参数。

downloadHandler(
reactive(file <- input$file1),     ## <--- here
filename = "report.doc",
content = function(file) {
# ...
}
)

这似乎打乱了CCD_ 4的整个逻辑;服务器错误";客户端上的消息,没有来自shine的错误或警告。

这一行需要删除才能成功下载文件

正确参考Rmd参数

如果要从Rmd报告中访问参数,则需要使用params$report.data。仅使用report.data将导致以下错误:object 'report.data' not found

---
output: word_document
params:
report.data: NULL
---
```{r}
report.data <- params$report.data
# ...
```

修复生成文件的路径

您正在临时目录中编织Rmd,这通常是个好主意。然而,找到正确的道路并不总是那么容易。在你的情况下,我使用了以下

rendered_report <- rmarkdown::render(
tempReport, output_file = "wordreport.doc",
params = params,
envir = new.env(parent = globalenv())
)
file.copy(rendered_report, file)

您的版本不起作用的原因是生成的报告是在tmpReport的临时目录中创建的。有关更多详细信息,请参阅?rmarkdown::render的参考文档。

我使用了rmarkdown::render()的返回值,它保存了生成文件的绝对路径。这不太容易出错,如果您事先不知道生成文件的文件扩展名,则特别有用

使用read.csv将上传的文件转换为data.frame

Shiny不会自动将上传的csv文件转换为数据帧。为此,您需要定义一个解析逻辑。

params <- list(report.data = read.csv(input$file1$datapath))

最后一句话

试着让你的编码项目更有条理,并将未来SO问题的范围限制在一次一个问题。创建";最小可重复实例";一开始可能看起来很乏味,但这样做有几个好处

  • 其他人可以阅读问题和答案,并在自己的项目中轻松重用它们,而无需解剖代码墙
  • 回答这些问题要容易得多。对于这样的问题,SO社区通常只提供评论,因为正确回答这些问题需要付出很多努力
  • 最小化和隔离问题是一项技能,它将帮助您更容易地在未来的编码项目中找出问题

相关内容

最新更新