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}
那么它就起作用了。 这当然不是很优雅,但有两个问题阻止你改变当前块的标签:
- 在代码块被执行之前,文件被parsing。 在执行任何代码或调用自定义钩子之前,parsing器已经检测到重复标签。
- 大块选项(包括标签)在钩子被调用之前被处理(逻辑:它是一个触发钩子的选项),所以钩子不能再改变标签。
未命名块的工作原理是在内部他们得到标签unnamed-chunk-
+块号。
块不能有重复的名称,因为内部knitr通过标签引用它们。 一个修复可能是使knitr将块号添加到具有重复名称的所有块。 或者用块数而不是标签来引用它们,但在我看来,这是一个更大的变化。