35

首先,我必须承认我对 knitr 和可重现分析的概念还很陌生,但我可以看到它在改进我当前的工作流程(其中包括大量复制粘贴到 word 文档中)方面的潜力。

我经常需要按组(在本例中为医院)生成多个报告,并且在每家医院内,我可能会报告许多不同的病房结果。以前我使用循环在 R 中运行我的所有绘图和分析,然后开始复制/粘贴工作;然而,在阅读了这篇文章后(Sweave 可以自动生成许多 pdf 文件吗?),它给了我希望,我实际上可以跳过许多步骤,直接从 R 到 Rnw/knitr 报告。

但是,在尝试之后,我发现有些东西不太有效(因为 Rnw 中的 R 环境似乎无法识别我试图传递给它的循环变量??)。

   ##  make my data
Hospital <- c(rep("A", 20), rep("B", 20))
Ward <- rep(c(rep("ICU", 10), rep("Medicine", 10)), 2)
Month <- rep(seq(1:10), 4)
Outcomes <- rnorm(40, 20, 5)
df <- data.frame(Hospital, Ward, Month, Outcomes)


##  Here is my current work flow-- produce all plots, but export as png and cut/paste
for(hosp in unique(df$Hospital)){
  subgroup <- df[ df$Hospital == hosp,]
  for(ward in unique(subgroup$Ward)){
    subgroup2 <- subgroup[subgroup$Ward == ward,]
    savename <- paste(hosp, ward)
    plot(subgroup2$Month, subgroup2$Outcomes, type="o", main=paste("Trend plot for", savename))
  }
}
# followed by much copy/pasting


##  Here is what I'm trying to go for using knitr 
library(knitr)
for (hosp in unique(df$Hospital)){
  knit("C:file.path\\testing_loops.Rnw", output=paste('report_', Hospital, '.tex', sep=""))
}

## With the following *Rnw file
## start *.Rnw Code
\documentclass[10pt]{article}
\usepackage[margin=1.15 in]{geometry}
<<loaddata, echo=FALSE, message=FALSE>>=
  Hospital <- c(rep("A", 20), rep("B", 20))
Ward <- rep(c(rep("ICU", 10), rep("Medicine", 10)), 2)
Month <- rep(seq(1:10), 4)
Outcomes <- rnorm(40, 20, 5)
df <- data.frame(Hospital, Ward, Month, Outcomes)
subgroup <- df[ df$Hospital == hosp,]
@

\begin{document}
<<setup, echo=FALSE >>=
  opts_chunk$set(fig.path = paste("test", hosp , sep=""))
@

Some infomative text about hospital \Sexpr{hosp}

<<plots, echo=FALSE >>=
  for(ward in unique(subgroup$Ward)){
    subgroup2 <- subgroup[subgroup$Ward == ward,]
    #     subgroup2 <- subgroup2[ order(subgroup2$Month),]
    savename <- paste(hosp, ward)
    plot(subgroup2$Month, subgroup2$Outcomes, type="o", main=paste("Trend plot for", savename))
  }
@
\end{document}


##  To be then turned into pdf with this
tools::texi2pdf("C:file.path\\report_A.tex", clean = TRUE, quiet = TRUE)

尝试运行我的 knit() 代码块后,我收到此错误:

Error in file(con, "w") : invalid 'description' argument

当我查看要创建 *.tex 文件的目录时,我可以看到医院 A 的 2 个 pdf 图已生成(B 没有),并且没有医院特定的 *.tex 文件可以编织成 pdf。提前感谢您提供的任何帮助!

4

3 回答 3

16

您不需要重新定义.Rnw文件中的数据,我认为警告来自您将输出名称与Hospital(医院的完整向量)而不是hosp(循环索引)放在一起的事实。

按照你的例子,testingloops.Rnw将是

\documentclass[10pt]{article}
\usepackage[margin=1.15 in]{geometry}
<<loaddata, echo=FALSE, message=FALSE>>=
subgroup <- df[ df$Hospital == hosp,]
@

\begin{document}
<<setup, echo=FALSE >>=
  opts_chunk$set(fig.path = paste("test", hosp , sep=""))
@

Some infomative text about hospital \Sexpr{hosp}

<<plots, echo=FALSE >>=
  for(ward in unique(subgroup$Ward)){
    subgroup2 <- subgroup[subgroup$Ward == ward,]
    #     subgroup2 <- subgroup2[ order(subgroup2$Month),]
    savename <- paste(hosp, ward)
    plot(subgroup2$Month, subgroup2$Outcomes, type="o", main=paste("Trend plot for", savename))
  }
@
\end{document}

并且驱动程序 R 文件将只是

##  make my data
Hospital <- c(rep("A", 20), rep("B", 20))
Ward <- rep(c(rep("ICU", 10), rep("Medicine", 10)), 2)
Month <- rep(seq(1:10), 4)
Outcomes <- rnorm(40, 20, 5)
df <- data.frame(Hospital, Ward, Month, Outcomes)

## knitr loop
library("knitr")
for (hosp in unique(df$Hospital)){
  knit2pdf("testingloops.Rnw", output=paste0('report_', hosp, '.tex'))
}
于 2013-03-13T22:34:59.150 回答
11

好问题!这适用于您在问题中提供的其他位。请注意,我已将您的替换hospx. 我已经调用了你的Rnw文件test.rnw

# input data
Hospital <- c(rep("A", 20), rep("B", 20))
Ward <- rep(c(rep("ICU", 10), rep("Medicine", 10)), 2)
Month <- rep(seq(1:10), 4)
Outcomes <- rnorm(40, 20, 5)
df <- data.frame(Hospital, Ward, Month, Outcomes)

# generate the tex files, one for each hospital in df
library(knitr)
lapply(unique(df$Hospital), function(x) 
       knit("C:\\emacs\\test.rnw", 
            output=paste('report_', x, '.tex', sep="")))

# generate PDFs from the tex files, one for each hospital in df
lapply(unique(df$Hospital), function(x)
       tools::texi2pdf(paste0("C:\\emacs\\", paste0('report_', x, '.tex')), 
                       clean = TRUE, quiet = TRUE))

我已经用lapply匿名函数替换了你的循环,这些函数似乎通常被认为更R-ish。

在这里您可以看到我在文件中替换hosp了的位置:xrnw

\documentclass[10pt]{article}
\usepackage[margin=1.15 in]{geometry}
<<loaddata, echo=FALSE, message=FALSE>>=
  Hospital <- c(rep("A", 20), rep("B", 20))
Ward <- rep(c(rep("ICU", 10), rep("Medicine", 10)), 2)
Month <- rep(seq(1:10), 4)
Outcomes <- rnorm(40, 20, 5)
df <- data.frame(Hospital, Ward, Month, Outcomes)
subgroup <- df[ df$Hospital == x,]
@

\begin{document}
<<setup, echo=FALSE >>=
  opts_chunk$set(fig.path = paste("test", x , sep=""))
@

Some informative text about hospital \Sexpr{x}

<<plots, echo=FALSE >>=
  for(ward in unique(subgroup$Ward)){
    subgroup2 <- subgroup[subgroup$Ward == ward,]
    #     subgroup2 <- subgroup2[ order(subgroup2$Month),]
    savename <- paste(x, ward)
    plot(subgroup2$Month, subgroup2$Outcomes, type="o", main=paste("Trend plot for", savename))
  }
@
\end{document}

结果是两个 tex 文件(report_A.tex、report_B.tex)、四个 PDF 用于图形(A1、A2、B1、B2)和两个 PDF 用于报告(report_A.pdf、report_B.pdf),每个都有它们的图形在他们中。那是你所追求的吗?

于 2013-03-13T21:59:52.067 回答
1

在这个答案中,我打算回答一个更一般的问题:“使用循环生成多个 pdf 报告”,而不是您的具体示例。这是因为这种趋势作为菜鸟很难追随。我设法让它最终工作(html版本),所以这是我谦虚的解决方案。这里可能发布了一些更好的,我只是还不能完全理解它们。

  1. 使用您的设计创建 RMD 文件并将其保存在 working\input 目录中(在 Rstudio 中:file->newfile->R markdown)。该文件应包含在报告中绘制图表所需的所有函数(只需在其中一个代码块中声明它们)。将此文件视为所有未来报告的模板。不要担心在早些时候咀嚼数据后将数据传递到它的环境中——我将在 (2) 中介绍这一点。要理解的关键问题是所有计算都在管道的下游完成(在您渲染 RMD 文件的那一刻)。

  2. 创建您需要在不同的控制 r 文件中使用的循环。就我而言,有一个循环遍历目录中的所有文件,并将它们放入数据框中。然后我想将这些数据帧连同其他数据变量一起传递到 RMD 中,以便绘制它们。这是它的完成方式:

    run_on_all<-function(path_in="path:\\where\\your\\input\\and\\RMD\\is", path_out="path:\\where\\your\\output\\will\\be") setwd(path_in) ibrary(rmarkdown) library(knitr) list_of_file_names=list.files(path = getwd, pattern = "*.csv") #this gets a list of the input files names for (file_name in list_of_file_names) { data=read.csv(file_name) #read file into data frame report_name=paste(some_variable_name,".html",sep="") render("your_template.Rmd",output_file =report_name,output_dir =path_out,list(data,all other parameters you want to input into the RMD))} }

  3. 最重要的命令是渲染函数调用。它允许您将任何您希望的参数放入 RMD 环境中。它还允许您更改报告的名称和更改输出位置。此外,通过调用它,您还可以生成报告,因此您可以在一行中得到所有信息。(请注意,如果对 RMD 的调用是在函数内,您可能会发现您输入的变量丢失了,但报告会仍然可以正确发布)

概括

您需要两个文件 - RMD 文件,这将是所有附加报告的模板和一个控制文件。控制文件获取数据,咀嚼它并将咀嚼的参数传递给RMD(通过渲染函数)。RMD 获取数据,进行一些计算,绘制它并将其发布到一个新文件中(也通过渲染函数)。我希望我有所帮助。

于 2018-01-01T18:51:48.547 回答