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被第二次调用时编织失败。 这个问题可以通过留下未命名的块来避免,因为自动生成唯一的标签。 然而,这并不理想,因为我想使用块标签为导出的图创build信息文件名。


一个潜在的解决scheme将使用一个简单的函数,将当前柱面添加到块标签:

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

但是似乎knitr并不会评估块标签位置中的expression式。


我也尝试使用修改当前块的标签的自定义块钩子 :

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

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


任何想法如何更改块标签,以便相同的子文档可以多次调用? 或者也许是一个替代的战略来完成这个?

对于任何碰到这篇文章的人来说,我想指出@Yihui在knitr 1.0中提供了一个正式的解决scheme ,引入了knit_expand()函数。 它工作得很好,真的简化了我的工作stream程。

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

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

如果你把所有的块都放在你的无名字中,也就是```{r}那么它就起作用了。 这当然不是很优雅,但有两个问题阻止你改变当前块的标签:

  1. 在代码块被执行之前,文件被parsing。 在执行任何代码或调用自定义钩子之前,parsing器已经检测到重复标签。
  2. 大块选项(包括标签)在钩子被调用之前被处理(逻辑:它是一个触发钩子的选项),所以钩子不能再改变标签。

未命名块的工作原理是在内部他们得到标签unnamed-chunk- +块号。

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