最近我似乎和合作者分享了很多代码。他们中的许多人是新手/中级R用户,并没有意识到他们必须安装他们还没有的包。

是否有一种优雅的方式来调用installed.packages(),比较那些我正在加载和安装如果丢失?


当前回答

在我的例子中,我想要一个可以从命令行(实际上是通过Makefile)运行的一行程序。下面是一个安装“VGAM”和“feather”的例子,如果它们还没有安装:

R -e 'for (p in c("VGAM", "feather")) if (!require(p, character.only=TRUE)) install.packages(p, repos="http://cran.us.r-project.org")'

在R内部,它就是:

for (p in c("VGAM", "feather")) if (!require(p, character.only=TRUE)) install.packages(p, repos="http://cran.us.r-project.org")

除了前面的解之外,这里没有别的解:

我只说一句 我硬编码回购参数(以避免任何弹出窗口询问使用的镜像) 我不想费心定义一个在其他地方使用的函数

还要注意重要的字符。only=TRUE(如果没有它,require将尝试加载包p)。

其他回答

非常基本的一个。

pkgs = c("pacman","data.table")
if(length(new.pkgs <- setdiff(pkgs, rownames(installed.packages())))) install.packages(new.pkgs)

上面的许多答案(以及这个问题的副本)依赖于安装。包装是不好的形式。从文档中可以看到:

当安装了数千个包时,这可能会很慢,所以不要使用它来查找是否安装了指定的包(使用system. exe)。或者查找一个包是否可用(调用require并检查返回值),或者查找少量包的详细信息(使用packageDescription)。每个安装的包需要读取几个文件,这在Windows和一些网络挂载的文件系统上会很慢。

因此,更好的方法是尝试使用require和install加载包,如果加载失败(如果没有找到require将返回FALSE)。我更喜欢这样的实现:

using<-function(...) {
    libs<-unlist(list(...))
    req<-unlist(lapply(libs,require,character.only=TRUE))
    need<-libs[req==FALSE]
    if(length(need)>0){ 
        install.packages(need)
        lapply(need,require,character.only=TRUE)
    }
}

可以这样使用:

using("RCurl","ggplot2","jsonlite","magrittr")

通过这种方式,它加载所有的包,然后返回并安装所有丢失的包(如果您愿意,可以在这里插入提示,询问用户是否想要安装包)。而不是调用install。对于每个包,它只传递一次卸载包的整个向量。

下面是相同的函数,但是有一个窗口对话框,询问用户是否想要安装缺少的包

using<-function(...) {
    libs<-unlist(list(...))
    req<-unlist(lapply(libs,require,character.only=TRUE))
    need<-libs[req==FALSE]
    n<-length(need)
    if(n>0){
        libsmsg<-if(n>2) paste(paste(need[1:(n-1)],collapse=", "),",",sep="") else need[1]
        print(libsmsg)
        if(n>1){
            libsmsg<-paste(libsmsg," and ", need[n],sep="")
        }
        libsmsg<-paste("The following packages could not be found: ",libsmsg,"\n\r\n\rInstall missing packages?",collapse="")
        if(winDialog(type = c("yesno"), libsmsg)=="YES"){       
            install.packages(need)
            lapply(need,require,character.only=TRUE)
        }
    }
}

今天,我偶然发现了rlang包提供的两个方便函数,即is_installed()和check_installed()。

从帮助页面(强调添加):

These functions check that packages are installed with minimal side effects. If installed, the packages will be loaded but not attached. is_installed() doesn't interact with the user. It simply returns TRUE or FALSE depending on whether the packages are installed. In interactive sessions, check_installed() asks the user whether to install missing packages. If the user accepts, the packages are installed [...]. If the session is non interactive or if the user chooses not to install the packages, the current evaluation is aborted.

interactive()
#> [1] FALSE
rlang::is_installed(c("dplyr"))
#> [1] TRUE
rlang::is_installed(c("foobarbaz"))
#> [1] FALSE
rlang::check_installed(c("dplyr"))
rlang::check_installed(c("foobarbaz"))
#> Error:
#> ! The package `foobarbaz` is required.

由reprex包在2022-03-25创建(v2.0.1)

使用lapply族和匿名函数方法,您可以:

尝试附加所有列出的包。 仅安装缺失(使用||惰性计算)。 尝试再次连接那些在第1步中丢失并在第2步中安装的组件。 打印每个包的最终加载状态(TRUE / FALSE)。 Req <- substitute(require(x, character。only = TRUE)) LBS <- c("plyr", "psych", "tm") Sapply (lbs, function(x) eval(req) || {install.packages(x);eval(点播)}) 心理学 真真真真

使用packrat使共享库完全相同,而不会改变其他环境。

就优雅和最佳实践而言,我认为你从根本上走错了方向。打包程序就是为这些问题而设计的。它是由RStudio由Hadley Wickham开发的。packrat使用自己的目录,将您的程序的所有依赖项安装在其中,而不涉及别人的环境,这样他们就不必安装依赖项并可能弄乱别人的环境系统。

Packrat is a dependency management system for R. R package dependencies can be frustrating. Have you ever had to use trial-and-error to figure out what R packages you need to install to make someone else’s code work–and then been left with those packages globally installed forever, because now you’re not sure whether you need them? Have you ever updated a package to get code in one of your projects to work, only to find that the updated package makes code in another project stop working? We built packrat to solve these problems. Use packrat to make your R projects more: Isolated: Installing a new or updated package for one project won’t break your other projects, and vice versa. That’s because packrat gives each project its own private package library. Portable: Easily transport your projects from one computer to another, even across different platforms. Packrat makes it easy to install the packages your project depends on. Reproducible: Packrat records the exact package versions you depend on, and ensures those exact versions are the ones that get installed wherever you go.

https://rstudio.github.io/packrat/