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

aar*_*len 40 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'}
```
Run Code Online (Sandbox Code Playgroud)

分析-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"))
```
Run Code Online (Sandbox Code Playgroud)

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


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

```r{paste('cur-label', cyl, sep = "-")}
```
Run Code Online (Sandbox Code Playgroud)

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


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

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

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


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

aar*_*len 39

对于遇到这篇文章的其他人,我想指出@Yihui 在knitr 1.0中提供了一个正式的解决方案,并引入了该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))`
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)


ROL*_*OLO 15

如果你在你的**名字中制作所有块,即```{r}它有效.当然,这不是很优雅,但有两个问题阻止您更改当前块的标签:

  1. 在执行代码块之前解析文件.在执行任何代码或调用自定义挂钩之前,解析器已检测到重复的标签.
  2. 在调用钩子之前处理块选项(包括标签)(逻辑:它是触发钩子的选项),因此钩子不能再更改标签.

未命名的块工作的事实是在内部它们获得标签unnamed-chunk-+块号.

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

  • 你的理解绝对正确,这是一个令人信服的案例,knitr需要一些改变.我现在正在看你的拉请求.谢谢! (7认同)