从RStudio调用的knitr不保留加载包的顺序

时间:2014-10-21 17:39:13

标签: r knitr rstudio dplyr

当我使用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,则不会发生此问题,但这仅仅是因为它会在环境中加载plyrdplyr个包(如果我重新启动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")
```

2 个答案:

答案 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)
@Yihui合并了this commit的请求,它可能会在CRAN中的knitr v1.8中提供(或者立即从GitHub或RForge中获得)。

当软件包加载到不相互依赖的不同块时,仍然可能存在问题,但这确实解决了上述问题以及我尝试过的其他应用程序中的示例。

答案 1 :(得分:3)

将此作为答案发布,因为它似乎比评论更具实质性。

tl; dr :尝试在运行之间手动删除cache/__packages(并将cache=FALSE添加到包加载块/不进行包缓存)并查看是否解决了问题......甚至添加

if (file.exists("cache/__packages")) unlink("cache/__packages")

(我还没有在你的例子中对此进行过测试。)

我有很多很多的包缓存问题,特别是在我运行大量不一致兼容包的示例的工作目录中。我经常手动删除cache/__packages。我想设计可以改进(但我还没有打算构建实例/思考如何改进设计)。