如何为R中的每一行数据帧生成markdown文档

jes*_*ssi 5 r knitr

我想从数据帧的每一行生成带有子文档的1个markdown文档,或者从数据帧生成nrows数量的markdown文档.降价文档是template.Rmd.

我认为它应该可以创建一个for循环,但是当我尝试这样做时,by(dataFrame, 1:nrow(dataFrame), function(row) knit(file = "/Users/path/template.Rmd"))我得到一个错误,输入意外结束.

Quitting from lines 23-26 (Preview-e0d353674d36.Rmd) 
Error in knit(file = "/Users/path/template.Rmd") : 
  unused argument (file = "/Users/path/template.Rmd")
Calls: <Anonymous> ... eval -> eval -> tapply -> lapply -> FUN -> FUN -> knit

Execution halted
Run Code Online (Sandbox Code Playgroud)

我尝试使用@Yihui解决的同样很棒的方法来编程引用带有knitr-expand的文本:R knitr:可以以编程方式修改块标签吗?

从该解决方案中,我们有两个.Rmd文件,我的报告和模板我的报告如下所示:

# My report

```{r}
data(mtcars)
cyl.levels <- unique(mtcars$cyl)
```

## Generate report for each level of cylinder variable
```{r, include=FALSE}
src <- lapply(cyl.levels, function(ncyl) knit_expand(file = "template.Rmd"))
```

`r knit(text = unlist(src))`
Run Code Online (Sandbox Code Playgroud)

模板看起来像:

```{r, results='asis'}
cat("### {{ncyl}} cylinders")
```

```{r mpg-histogram-{{ncyl}}cyl}
hist(mtcars$mpg[mtcars$cyl == {{ncyl}}], 
  main = paste({{ncyl}}, "cylinders"))
```

```{r weight-histogam-{{ncyl}}cyl}
hist(mtcars$wt[mtcars$cyl == {{ncyl}}], 
  main = paste({{ncyl}}, "cylinders"))
```
Run Code Online (Sandbox Code Playgroud)

此解决方案为每个级别的柱面生成单个降价文档,其中包含子文档(在标题级别2).但是,我正在尝试创建一个获取.csv的报表,然后创建并修改数据框并为另一个数据帧的每一行生成内容.

我认为我坚持的是如何使用{{ncyl}}中的值以编程方式引用数据库的行.我希望能够使用{{ncyl}}的级别来对数据帧mtcars中的相关行进行处理(假设此示例中只有行==级别{{ncyl}}).

虽然data(mtcars)行数确实比cylyinder的行数多,但R将{{ncyl}}的值存储为整数.因此,您可以调用mtcars$gear[[{{ncyl}}]]并获取{{ncyl}}行的齿轮值.

为什么然后,当我们将它添加到我们的template.Rmd中时,它会失败?

原谅我,它不会失败,它会给我们,gear <- mtcars$gear[[{{ncyl}}]]但我们不能创造一大块装备,就像```{r this-gear-{{gear}}}.

这有效

```{r}
gear <- mtcars$gear[[{{ncyl}}]]
gear
```

```{r, results='asis'}
cat("### {{ncyl}} cylinders")
```

```{r mpg-histogram-{{ncyl}}cyl}
hist(mtcars$mpg[mtcars$cyl == {{ncyl}}], 
  main = paste({{ncyl}}, "cylinders"))
```

```{r weight-histogam-{{ncyl}}cyl}
hist(mtcars$wt[mtcars$cyl == {{ncyl}}], 
  main = paste({{ncyl}}, "cylinders"))
```
Run Code Online (Sandbox Code Playgroud)

这不起作用

```{r}
gear <- mtcars$gear[[{{ncyl}}]]
gear
```

```{r, results='asis'}
cat("### {{ncyl}} cylinders")
```

```{r mpg-histogram-{{ncyl}}cyl}
hist(mtcars$mpg[mtcars$cyl == {{ncyl}}], 
  main = paste({{ncyl}}, "cylinders"))
```

```{r weight-histogam-{{ncyl}}cyl}
hist(mtcars$wt[mtcars$cyl == {{ncyl}}], 
  main = paste({{ncyl}}, "cylinders"))
```
```{r {{gear}}}
gear
```
Run Code Online (Sandbox Code Playgroud)

给出错误

Quitting from lines 10-12 (Preview-e0d32d687661.Rmd) 
Error in eval(expr, envir, enclos) : object 'gear' not found
Calls: <Anonymous> ... knit_expand -> inline_exec -> withVisible -> eval -> eval
Execution halted
Run Code Online (Sandbox Code Playgroud)

我想我正在接近主要问题"我如何为数据帧的每一行创建一个降价文档?" 编织扩展功能有问题.

有人可以帮助我理解:1.如何解决主要问题2.为什么{{gear}}在template.Rmd中不起作用?

所以,我仍然不明白(2),但我认为@daroczig让我接近理解解决主要问题的一种方法.我不认为这是一个问题太独特,我认为有一种方法可以解决它没有brewpanderrapport.在任何情况下,我采用brew方法并使用几行数据帧执行某些操作.它抛出一个错误.注意我没有对这段代码做任何明智的事情,只是限制mtcars为3行,所以我没有得到太多的输出,然后在 for 循环中创建另一个,蹩脚的数据帧.

# My report

<%
mtcars1 <- mtcars[1:3,]
mtcars1$type <- c('red','blue','green')
t.levels <- unique(mtcars1$type)
for (ty in t.levels) {
p <- subset(mtcars1,type == ty) 
x <- rep(p, 4)
short <- paste0(p$gear, p$mpg)
%>

### <%= short %> blah

<%=
hist(x$mpg, main = paste(short, "blah"))
%>

<% } %>
Run Code Online (Sandbox Code Playgroud)

这只是对@daroczig下面提出的解决方案的一点点修改.如果我们命名demo.brew并从中调用它,它就可以工作 Pandoc.brew('demo.brew', output = tempfile(), convert = 'html').做一个愚蠢的例子.

(3)有没有一个如何在没有酿造的情况下做到这一点的例子?我很好奇.

回答(3)是的.这适用于调用变量而不是行号的for循环

varlist <- unique(df$variable)
for (var in varlist) {
    try(knit2html(input= '/Users/path/template.Rmd',
                  output=paste0('/Users/path/template',var,'.html'))) 
Run Code Online (Sandbox Code Playgroud)

适用于1:nrow()的循环没有.

dar*_*zig 3

pander基于我上面的评论的替代解决方案:

# My report

<%
cyl.levels <- unique(mtcars$cyl)
for (ncyl in cyl.levels) {
%>

### <%= ncyl %> cylinders

<%=
hist(mtcars$mpg[mtcars$cyl == ncyl], main = paste(ncyl, "cylinders"))
hist(mtcars$wt[mtcars$cyl == ncyl], main = paste(ncyl, "cylinders"))
%>

<% } %>
Run Code Online (Sandbox Code Playgroud)

要生成此文件(名为demo.brew),请运行:

Pandoc.brew('demo.brew')
Run Code Online (Sandbox Code Playgroud)

或者获取 MS Word 文档:

Pandoc.brew('demo.brew', output = tempfile(), convert = 'docx')
Run Code Online (Sandbox Code Playgroud)

更新:我刚刚意识到您需要针对类别的单独文档。为此,我建议尝试一下我的另一个包,rapport它专注于精确的统计报告模板。快速示例:

<!--head
meta:
  title: Demo for @Jessi
  author: daroczig
  description: This is a demo
  packages: ~
inputs:
- name: ncyl
  class: integer
  standalone: TRUE
  required: TRUE
head-->

### <%= ncyl %> cylinders

<%=
hist(mtcars$mpg[mtcars$cyl == ncyl], main = paste(ncyl, "cylinders"))
hist(mtcars$wt[mtcars$cyl == ncyl], main = paste(ncyl, "cylinders"))
%>
Run Code Online (Sandbox Code Playgroud)

所以上面的文档 ( demo.rapport) 是一个rapport模板,它有一个用于元数据和输入的 YAML 标头(其作用类似于 R 函数中的参数/参数),然后正文可以包含 markdown 和语法为 的 Rbrew代码pander。现在您可以通过简单的调用轻松调用此报告模板,例如 4 个气缸:

> rapport('demo.rapport', ncyl = 4)

### _4_ cylinders

![](plots/rapport--home-daroczig-projects-demo.rapport-6-1.png)
![](plots/rapport--home-daroczig-projects-demo.rapport-6-2.png)
Run Code Online (Sandbox Code Playgroud)

要为所有气缸生成 MS Word 文件,请尝试以下操作:

for (ncyl in (2:4)*2) {
    rapport.docx('/home/daroczig/projects/demo.rapport', ncyl = ncyl)
}
Run Code Online (Sandbox Code Playgroud)