R knitr:可以以编程方式修改块标签吗?

时间:2012-08-23 15:27:38

标签: r knitr

我正在尝试使用knitr生成一个报告,该报告在数据集的不同子集上执行相同的分析集。该项目包含两个Rmd文件:第一个文件是设置工作空间和文档的主文档,第二个文件仅包含执行分析并生成相关数据的块。

我想要做的是编织主文件,然后调用每个数据子集的第二个文件并将结果包含在单个文档中。下面是一个简单的例子。

主文件:

# My report

```{r}
library(iterators)
data(mtcars)
```

```{r create-iterator}
cyl.i <- iter(unique(mtcars$cyl))
```

## Generate report for each level of cylinder variable
```{r cyl4-report, child='analysis-template.Rmd'}
```

```{r cyl6-report, child='analysis-template.Rmd'}
```

```{r cyl8-report, child='analysis-template.Rmd'}
```

分析-template.Rmd:

```{r, results='asis'}
cur.cyl <- nextElem(cyl.i)
cat("###", cur.cyl)
```

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

```{r weight-histogam}
hist(mtcars$wt[mtcars$cyl == cur.cyl], main = paste(cur.cyl, "cylinders"))
```

问题是knitr不允许使用非唯一的块标签,因此第二次调用analysis-template.Rmd时编织失败。通过保留未命名的块可以避免此问题,因为将自动生成唯一标签。然而,这并不理想,因为我想使用块标签为导出的图创建信息文件名。


一个潜在的解决方案是使用一个简单的函数将当前柱面附加到块标签:

```r{paste('cur-label', cyl, sep = "-")}
```

但似乎knitr不会评估块标签位置的表达式。


我还尝试使用修改当前chunk标签的自定义chunk hook

knit_hooks$set(cyl.suffix = function(before, options, envir) {
    if (before) options$label <- "new-label"
})

但是更改块标签不会影响生成的图的文件名,所以我不认为knitr正在使用新标签。


有关如何更改块标签的任何想法,以便可以多次调用相同的子文档?或者也许是实现这一目标的另一种策略?

3 个答案:

答案 0 :(得分:37)

对于遇到这篇文章的其他人,我想指出@Yihui在knitr 1.0中提供了formal solution这个问题,引入了knit_expand()函数。它运行良好,真正简化了我的工作流程。

例如,以下内容将针对mtcars$cyl的每个级别处理下面的模板脚本,每次使用其当前值替换{{ncyl}}(在模板中)的所有实例:

# 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))`

模板:

```{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"))
```

答案 1 :(得分:15)

如果你的**名字中的所有块都是无名的,即```{r}它可以正常工作。当然,这不是很优雅,但是有两个问题阻止你改变当前块的标签:

  1. 在执行代码块之前解析文件。在执行任何代码或调用自定义挂钩之前,解析器已经检测到重复的标签。
  2. 在调用挂钩之前处理块选项(包括标签)(逻辑:它是触发挂钩的选项),因此挂钩不能再更改标签。
  3. 未命名的块工作的事实是在内部它们获得标签unnamed-chunk- +块号。

    块不能具有重复的名称,因为内部编织器通过标签引用它们。修复可能是让knitr将块号添加到具有重复名称的所有块。或者用块数而不是标签来引用它们,但在我看来这是一个更大的变化。

答案 2 :(得分:1)

存在一个类似的问题here,我能够使用knit_expand(text =)根据输入图的任意列表,以编程方式创建r个块并编织输出以用于flexdashboard(非常有用)中和keytool -list -printcert -jarfile file.apk 方法。