如何使代码块依赖于knitr/rmarkdown中以前的所有块?

uma*_*ani 11 r knitr

目标

我想通过使块依赖于所有以前的块来创建可重现的数据分析.因此,如果有3个块并且我在第一个块中更改某些内容,则后续的2个块应该重新运行,以便它们反映输出中所做的更改.我想在文档顶部的全局块选项中添加这个条件,这样我就不必多次使用了dependson.

问题

如果未修改块,则块的输出不会更改cache=TRUE.对于包含代码的块,我可以使用文档顶部的以下内容使它们可靠地依赖于所有以前的代码:

```{r setup, echo=FALSE}
# set global chunk options: 
library(knitr)
opts_chunk$set(cache=TRUE, autodep = TRUE)
dep_auto()
```
Run Code Online (Sandbox Code Playgroud)

如果更改了上述任何块,则重新运行所有后续块.但是如果我使用source()块来读取R脚本,这不起作用.以下是一个示例文档:

---
title: "Untitled"
output: html_document
---
```{r setup, echo=FALSE}
# set global chunk options: 
library(knitr)
opts_chunk$set(cache=TRUE, autodep = TRUE)
dep_auto()
```


# Create Data
```{r}
#source("data1.R")
x <- data.frame(col1 = 4:10, col2 = 6:12)
x
```

# Summaries
```{r}
#source("data2.R")

median1.of.x <- sapply(x, function(x) median(x)-1)

sd.of.x <- sapply(x, sd)

plus.of.x <- sapply(x, function(x) mean(x)+1)

jj <- rbind(plus.of.x, sd.of.x, median1.of.x)

```

```{r}
jj
```
Run Code Online (Sandbox Code Playgroud)

现在,如果我更改了前2个块中的任何一个,则第三个块在knitting 之后给出正确的输出.但是如果相反我将第一个块的代码放在源文件中data1.R,第二个块放在文件中data2.R,保持全局块选项与之前相同,如果我对源文件进行任何更改,它们就不会正确地反映在第三个块的输出中.例如,更改xx <- data.frame(col1 = 5:11, col2 = 6:12)应该产生:

 > jj
                 col1      col2
plus.of.x    9.000000 10.000000
sd.of.x      2.160247  2.160247
median1.of.x 8.000000  9.000000 
Run Code Online (Sandbox Code Playgroud)

但是,source()如上所述,该knitr文件报告:

 jj
##                col1      col2
## mean.of.x  5.000000  9.000000
## sd.of.x    2.160247  2.160247
## minus.of.x 6.000000 10.000000 
Run Code Online (Sandbox Code Playgroud)

我需要更改哪些设置才能sourceknitr文档中正确使用?

Yih*_*Xie 13

使用时source(),knitr无法分析从中创建的可能对象; knitr必须能够看到完整的源代码来分析代码块之间的依赖关系.有两种方法可以解决您的问题:

  1. 告诉第二个块它依赖于x通过添加使用值的任意块选项的值x,例如```{r cache.extra = x}; 然后每当x更改时,此代码块的缓存将自动失效(更多信息);
  2. knitr看到完整的源代码; 您可以通过chunk选项将源代码传递给代码块code,例如```{r code = readLines('data1.R')}(相同data2.R); 然后dep_auto()应该能够弄清楚x是从第一个块创建的,并在第二个块中使用,所以第二个块必须依赖于第一个块.

  • 在Yihui的第一个建议的基础上,您可以引入`cache.extra = tools :: md5sum("data1.R")`,它将检查文件中是否有任何变化(尽管第二个建议似乎更好,如果可能的话). (3认同)
  • @umairdurrani我这里没有一般的建议,但是如果你想把一些R代码放在单独的R脚本中,你可以使用我提到的`code`选项,或`@ read_chunk()`作为@Ben提到(你会有标记代码块).`source()`一般都很好,我想不出其他可能有问题的情况. (2认同)