从多个Rmd文件中缓存knitr外部代码

5
我在使用knitr时遇到了困难,它无法在两个共享外部R文件源代码的Rmd文档之间利用缓存。尽管我可以在文件系统中看到两个文档都将输出写入同一组缓存文件中,但每次一个Rmd文档被编织成HTML时,它都会覆盖先前编织的Rmd生成的缓存文件。对同一Rmd文件的多次编织成功利用缓存而不重新执行共享代码。我在配置缓存选项以支持多个文档时是否遗漏了什么?以下是示例代码和sessionInfo()转储。感谢您提供的任何帮助。 test1.R
## @knitr source_chunk_1
x <- Sys.time()
x

test1a.Rmd

```{r set_global_options, cache=FALSE}
library(knitr)
opts_knit$set(self.contained = FALSE)
opts_chunk$set(cache = TRUE, cache.path = "knitrcache/test-")
read_chunk("test1.R")
```

```{r local_chunk_1, ref.label="source_chunk_1"}
```

test1b.Rmd

```{r set_global_options, cache=FALSE}
library(knitr)
opts_knit$set(self.contained = FALSE)
opts_chunk$set(cache = TRUE, cache.path = "knitrcache/test-")
read_chunk("test1.R")
```

```{r local_chunk_1, ref.label="source_chunk_1"}
```

sessionInfo

> sessionInfo()
R version 3.1.0 (2014-04-10)
Platform: x86_64-w64-mingw32/x64 (64-bit)

locale:
[1] LC_COLLATE=English_United States.1252  LC_CTYPE=English_United States.1252           
LC_MONETARY=English_United States.1252
[4] LC_NUMERIC=C                           LC_TIME=English_United States.1252    

attached base packages:
[1] stats     graphics  grDevices utils     datasets  methods   base     
other attached packages:
[1] knitr_1.5
loaded via a namespace (and not attached):
[1] evaluate_0.5.3   formatR_0.10     rmarkdown_0.2.05 stringr_0.6.2    tools_3.1.0     

1
我必须承认,我从未预料到这一点会在第一时间就奏效——如果它能够奏效那将是很好的,但我不认为它是被设计成那样的……?(你能指出哪些文档表明应该期望它能够奏效吗?)我可能会退回到手动保存和加载文件的系统(可能会使逻辑“块”更大,以便不会每几行就加载和保存位……)。 - Ben Bolker
1
Yihui在回应早期的帖子(http://stackoverflow.com/questions/17503843/how-to-cache-knitr-chunks-across-two-or-more-files?rq=1)时表示可以实现。我也阅读了http://yihui.name/knitr/demo/cache/,认为这是可能的。ref.label选项(http://yihui.name/knitr/demo/reference/)似乎是专门为此而创建的。检查knitr源代码,问题似乎在于为缓存创建哈希码。不确定为什么上面的示例代码会导致哈希值更改并覆盖缓存。 - Wil McKoy
1个回答

1
在从Github下载并研究knitr源代码后,我相信已经找到了问题的根源。block.R中的代码通过使用处理的代码块的内容和选项调用digest()函数来设置缓存的哈希值:
hash = paste(valid_path(params$cache.path, label), digest::digest(content), sep = '_')

我暂时插入了代码,用于输出每个样本Rmd脚本中存储在内容对象中的数据。默认的fig.path选项值是它们之间唯一不同的组成部分。

 > content$fig.path
[1] "./test1a_files/figure-html/"  

> content$fig.path
[1] "./test1b_files/figure-html/"

在每个Rmd文件中设置全局fig.path会导致内容对象和生成的哈希值相同。现在,当我编译这两个Rmd文件时,它们都使用相同的缓存值。

Test1.R

## @knitr source_chunk_1
x <- Sys.time()
x

test1a.Rmd

```{r set_global_options, cache=FALSE}
library(knitr)
opts_knit$set(self.contained = FALSE)
opts_chunk$set(cache = TRUE, cache.path = "knitrcache/test-", fig.path = "knitrfig/test-")
read_chunk("test1.R")
```

```{r local_chunk_1, ref.label="source_chunk_1"}
``` 

test1b.Rmd

```{r set_global_options, cache=FALSE}
library(knitr)
opts_knit$set(self.contained = FALSE)
opts_chunk$set(cache = TRUE, cache.path = "knitrcache/test-", fig.path = "knitrfig/test-")
read_chunk("test1.R")
```

```{r local_chunk_1, ref.label="source_chunk_1"}
``` 

我很好奇,为什么你不把常见的代码块(比如上面例子中的set_global_options)放在单独的文件中,利用knitr子文档功能:http://yihui.name/knitr/demo/child。如果我理解正确,这类似于C语言的`include`功能。 - Aleksandr Blekh

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接