对于我的一个脚本,我想编写一个R函数来检查是否已经安装了一个包:如果是,它应该使用library()将其导入到命名空间中,否则它应该安装并导入它。
我认为 pkgname 是一个字符串,并尝试编写如下内容:
ensure_library <- function(pkgname) {
if (!require(pkgname)) {
install.packages(pkgname, dependencies = TRUE)
}
require(pkgname)
}
这很简单,这个功能不起作用。
如果我尝试像ensure_library("dplyr")
那样运行它,它会安装包dplyr但是它会失败,因为它试图在命名空间中导入pkgname
而不是dplyr
。
ensure_library("dplyr")
Loading required package: pkgname
Installing package into ‘/home/luca/R-dev’
(as ‘lib’ is unspecified)
trying URL 'https://cran.rstudio.com/src/contrib/dplyr_0.5.0.tar.gz'
Content type 'application/x-gzip' length 708476 bytes (691 KB)
==================================================
downloaded 691 KB
* installing *source* package ‘dplyr’ ...
** package ‘dplyr’ successfully unpacked and MD5 sums checked
** libs
.... a lot of compiling here....
installing to /home/luca/R-dev/dplyr/libs
** R
** data
*** moving datasets to lazyload DB
** inst
** preparing package for lazy loading
** help
*** installing help indices
** building package indices
** installing vignettes
** testing if installed package can be loaded
* DONE (dplyr)
The downloaded source packages are in
‘/tmp/Rtmpfd2Lep/downloaded_packages’
Loading required package: pkgname
Warning messages:
1: In library(package, lib.loc = lib.loc, character.only = TRUE, logical.return = TRUE, :
there is no package called ‘pkgname’
2: In library(package, lib.loc = lib.loc, character.only = TRUE, logical.return = TRUE, :
there is no package called ‘pkgname’
此外,如果我现在重新运行它,它将再次安装dplyr
。
我意识到这可能是由于R非标准评估,我尝试了几种eval / substitute / quote组合,以使其与require
一起使用,但我无法成功。< / p>
有人可以帮我理解发生了什么,是否有一些简单的解决方法?
如果已经实现此功能的功能存在,我想知道,但我真正感兴趣的是理解为什么我的代码无法正常工作。
答案 0 :(得分:3)
扩展使用character.only=TRUE
的建议:如果您查看require
的代码,您会看到第一步仅在&#39; character.only&#39的默认值下执行; (= FALSE
)持有:
> require
function (package, lib.loc = NULL, quietly = FALSE, warn.conflicts = TRUE,
character.only = FALSE)
{
if (!character.only)
package <- as.character(substitute(package))
loaded <- paste("package", package, sep = ":") %in% search()
if (!loaded) {
if (!quietly)
packageStartupMessage(gettextf("Loading required package: %s",
package), domain = NA)
value <- tryCatch(library(package, lib.loc = lib.loc,
character.only = TRUE, logical.return = TRUE, warn.conflicts = warn.conflicts,
# snipped rest of code
因此,保留character.only的默认值会强制函数将符号pkgname
转换为字符值。
as.character(substitute(pkgname))
[1] "pkgname"
因为&#39; character.only&#39;也是library
逻辑的一部分,需要调用library
,您可以使用library
。
进一步评论:你发布了一个关于Rhelp的后续行动,得到了Duncan Murdoch和Peter Dalgaard的一些有用的答案,它澄清了(我希望)这个问题。在这个过程中,我想知道你是否对这个答案的抵制是因为这个函数的名称设置了替换应该发生但没有发生任何看起来像&#34;替换&#34 ;。这种期望似乎是完全合理的,我现在看起来很迟疑。我认为函数的正确名称可能是:substitute_but_only_on_the_basis_of_the_local_environment_or_second_argument。 substitute
更常见的用法是两个参数:
y_val=45; a_val=99
substitute( x + y == z + a , list( y= y_val, a = a_val)
x + 45 == z + 99
没有努力&#39;检查第一个参数中任何符号的值,除非在第二个参数中有一个命名项(名为env
。)
答案 1 :(得分:-2)
上面给出的建议已经很好,可以解决您的问题。尽管如此,你在那里重新发明了轮子。
如果您想分发R代码,文档中包含对外部软件包的要求并且可能需要进行适当的测试,我建议您从中创建一个软件包。安装软件包时,会自动确保所有依赖项都可用。此外,您还拥有文档和测试脚本的位置。它可以很好地保存所有内容并同时进行版本控制。