如何在knitr rmd文件中优雅地+健壮地缓存外部脚本?

时间:2015-07-10 08:36:23

标签: r caching knitr

说,我有一个外部R脚本external.R

df.rand <- data.frame(rnorm(n = 100), rnorm(n = 100))

然后是main.Rmd

\documentclass{article}

\begin{document}

<<setup, include = FALSE>>=
library(knitr)
library(ggplot2)
# global chunk options
opts_chunk$set(cache=TRUE, autodep=TRUE, concordance=TRUE, progress=TRUE, cache.extra = tools::md5sum("external.r"))
@

<<source, include=FALSE>>=
source("external.R")
@


<<plot>>=
ggplot(data = df.rand, mapping = aes(x = x, y = y)) + geom_point()
@

\end{document}

在外部脚本中使用它是有帮助的,因为实际上,这是一堆污染main.Rmd的导入,数据清理和模拟任务。

main.Rmd中的任何块都依赖于外部脚本中的更改。 为了解释此依赖关系,我添加了上述cache.extra = tools::md5sum("external.r")

这似乎没问题。

我正在寻找最佳实践。

  • 健壮(足够)?
  • 有更强大的优雅方式吗? (例如,遗憾的是external.R中的任何更改都会触发完整的缓存失效,而不仅仅是使实际更改的对象无效。“

没有副作用(某些library()来电除外,但我可以将它们移至main.Rmd)。

我总是担心我在某种程度上做错了

1 个答案:

答案 0 :(得分:2)

应该有比目前使用的自助缓存更好的方法。首先,您可以将external.R拆分为块:

# ---- CreateRandomDFs----
df.rand1 <- data.frame(rnorm(n = 100), rnorm(n = 100))
df.rand2 <- data.frame(rnorm(n = 100), rnorm(n = 100))

# ---- CreateOtherObjects----

# stuff

main.Rmd中,添加(在未缓存的块中!)read_chunk(path = 'external.R')。然后执行块:

<<CreateRandomDFs>>=
@
<<CreateOtherObjects>>=
@

如果autodep不起作用,请将dependson添加到您的块中。仅使用df.rand1df.rand2的块获取dependson = "CreateRandomDFs";当还使用其他对象时,设置dependson = c("CreateRandomDFs", "CreateOtherObjects")

当特定对象发生变化时,您也可能使块缓存失效:cache.whatever = quote(df.rand1)

这样,您可以通过external.R中的任何更改来避免使整个缓存失效。将文件中的代码拆分为块是至关重要的:如果使用太多的块,则必须列出许多依赖项;如果你使用太少的块,缓存会更多/太频繁地失效。