当我使用Knit HTML按钮渲染在RStudio中使用缓存块的Rmd markdown文件时,我发现加载包的顺序不会从块到块被记住。当我需要以特定顺序加载包以避免命名空间冲突时,这会导致问题。
对于可重现的示例(需要安装plyr,dplyr和pryr软件包,请参见下文),我首先创建一个knitr Rmd文档,加载plyr然后加载dplyr(它们都导出summarise
函数),然后使用pryr来确定找到哪个汇总函数。我用RStudio" Knit HTML"编织了这个。按钮:
```{r}
library(knitr)
opts_chunk$set(cache = TRUE, message = FALSE)
```
```{r test1}
library(plyr)
library(dplyr)
```
```{r test2, dependson = "test1"}
attr(pryr::where("summarise"), "name")
```
根据建议here,我在dplyr之前加载plyr,以便dplyr的函数应该首先出现在搜索路径中。正如所料,输出md文件显示summarise
函数来自dplyr:
attr(pryr::where("summarise"), "name")
## [1] "package:dplyr"
然而,如果我在test2
块中做了一些小改动:
```{r test2, dependson = "test1"}
attr(pryr::where("summarise"), "name") # this is a change
```
导致它被重新编译,它现在以错误的顺序加载包,并且在plyr中找到summarise
:
attr(pryr::where("summarise"), "name") # this is a change
## [1] "package:plyr"
请注意,如果从R命令行运行knit
,则不会发生此问题,但这仅仅是因为它会在环境中加载plyr
和dplyr
个包(如果我重新启动R,则会出现同样的问题。)
我知道我可以将函数称为dplyr::summarise
以避免冗余,但这非常麻烦。完全不加载plyr
不是一个选项,因为几个包无意中将它添加到命名空间。如何确保按所需顺序加载包?
我使用的是最新版本的RStudio(0.98.1079),我的sessionInfo如下:
## R version 3.1.1 (2014-07-10)
## Platform: x86_64-apple-darwin13.1.0 (64-bit)
##
## locale:
## [1] en_US.UTF-8/en_US.UTF-8/en_US.UTF-8/C/en_US.UTF-8/en_US.UTF-8
##
## attached base packages:
## [1] stats graphics grDevices utils datasets methods base
##
## other attached packages:
## [1] plyr_1.8.1 dplyr_0.3.0.2 knitr_1.7
##
## loaded via a namespace (and not attached):
## [1] assertthat_0.1 codetools_0.2-8 DBI_0.3.0 digest_0.6.4
## [5] evaluate_0.5.5 formatR_1.0 htmltools_0.2.4 magrittr_1.0.0
## [9] parallel_3.1.1 pryr_0.1.0.9000 Rcpp_0.11.2 rmarkdown_0.3.10
## [13] rstudioapi_0.1 stringr_0.6.2 tools_3.1.1
请注意,如有必要,您可以使用以下命令为此可重现示例设置必要的包:
```{r}
install.packages(c("devtools", "plyr", "dplyr"))
devtools::install_github("hadley/pryr")
```
答案 0 :(得分:5)
My pull request knitr通过保留__packages
文件中搜索路径的顺序来解决此问题。相关代码是:
x = rev(.packages())
if (file.exists(path))
x = setdiff(c(readLines(path), x), .base.pkgs)
writeLines(x, path)
当软件包加载到不相互依赖的不同块时,仍然可能存在问题,但这确实解决了上述问题以及我尝试过的其他应用程序中的示例。
答案 1 :(得分:3)
将此作为答案发布,因为它似乎比评论更具实质性。
tl; dr :尝试在运行之间手动删除cache/__packages
(并将cache=FALSE
添加到包加载块/不进行包缓存)并查看是否解决了问题......甚至添加
if (file.exists("cache/__packages")) unlink("cache/__packages")
(我还没有在你的例子中对此进行过测试。)
我有很多很多的包缓存问题,特别是在我运行大量不一致兼容包的示例的工作目录中。我经常手动删除cache/__packages
。我想设计可以改进(但我还没有打算构建实例/思考如何改进设计)。