一次性加载多个软件包

231

我如何一次性加载多个包而不需要重复输入require命令?我尝试了三种方法,但都失败了。

基本上,我想要提供一个包名向量给一个函数,然后这个函数可以加载它们。

x<-c("plyr", "psych", "tm")

require(x)
lapply(x, require)
do.call("require", x)
10个回答

317

你提出的几种函数排列方式是可以工作的 -- 但只有在指定character.only参数为TRUE时才有效。快速示例:

lapply(x, require, character.only = TRUE)

7
你可以利用部分字符匹配,使用 lapply(x, require, ch = T) 或者甚至是 lapply(x, require, c = T)。 - Dason
1
@daroczig 这段代码加载了包,但为什么会出现以下警告信息: 1:在library(package,lib.loc = lib.loc,character.only = TRUE,logical.return = TRUE,)中:没有名为“x”的包 2:如果(!loaded){:条件长度> 1,只有第一个元素将被使用 - Anusha
1
@Anusha:我一定错过了某些明显的东西,但我从未在我的回答中输入过“do.call”,所以你的回复让我有点困惑。 - daroczig
1
@PauloCardoso:没错。虽然我本来认为更适合使用类似于lapply(x, function(x) {if (!require(x, character.only=T)) {install.packages(x);require(x)}})这样的方式,在需要时才进行先前检查并安装所需的包。如果我们以字符形式在x中指定要加载(以及必要时安装)的包的列表,就像OP所要求的那样。但是在评论中进一步开发这个想法会变得相当冗长 :) - daroczig
34
如果R::base能够原生支持library()函数中的这个lapply技巧那就太好了。这样就可以很方便地使用类似于library(c("plyr", "umx"))这样的语法了。 - tim
显示剩余7条评论

86

我维护的CRAN软件包pacman(与Dason Kurkiewicz合著)可以完成此操作:

因此,用户可以执行以下操作:

## install.packages("pacman")
pacman::p_load(dplyr, psych, tm) 

如果缺少软件包,p_load 将从 CRAN 或 Bioconductor 下载它。


9
为什么选择 p_load 这样的简短名称?使用更描述性的名称,比如 load_packages,可以更清晰地表达函数的意图。 - Paul Hiemstra
25
因为 p 代表 package(软件包),每个实用且被导出的软件包内函数都以 p_ 开头。我们还倾向于使用 library(库),这是额外的 7 个字符。7 个字符 x ~1000000 次函数使用寿命 x 每个字符 0.5 秒 = 3500000 秒。这相当于 58333.33 分钟、972.2222 小时或 40.50926 天的程序员生命,我们已经为他们节省回来了 :-) 无论如何,我们的目标是在 2 月 1 日前推广到 CRAN。 - Tyler Rinker
4
大约晚了一年,但我们终于向CRAN提交了。应该在几天内上线。@trinker(或我)确保在它公开后进行修改。 - Dason
6
@Tyler,虽然我晚了几年,但我认为你对p_前缀的理由很靠不住。如果简洁是问题,可以完全删除p_前缀。事实上,在其他语言中通常不建议使用这样的前缀,有很好的原因(我已经告诉过 Hadley 在 forcats 中使用 fct_ 也是同样如此)。这一点特别适用于使用限定名称空间 (pacman::) 的包的预期使用方式。 - Konrad Rudolph
5
对于在这个问题上表现过于争执,我很抱歉,但我确实认为 R 社区在这里是错误的,而几乎所有其他现代语言都做得对:你说“这可以防止命名空间冲突。” 但是这就是命名空间存在的意义!包作者的责任是教育人们正确使用包,而不是容忍他们的粗糙编程实践。 - Konrad Rudolph
显示剩余5条评论

25

这应该就可以解决问题了:

lapply(x, FUN = function(X) {
    do.call("require", list(X)) 
})

重要的是,在do.call(what, args)中的args参数必须是一个列表,即使它只有一个元素!


21

我认为@daroczig提供的代码可以通过将require替换为library并将lapply调用包装在invisible()函数中来进行改进。因此,改进后的代码将如下所示:

invisible(lapply(x, library, character.only = TRUE))

这段代码得到改进,因为:

  1. library() 一般比 require() 更受欢迎,用于加载包,因为前者如果未安装该包,则会出现错误,而后者只会给出警告。此外,require() 调用 library(),那么为什么不直接使用 library() 呢!

    library("time")
    # Error in library("time") : there is no package called ‘time’
    
    require("time")
    # Loading required package: time
    # Warning message:
    # In library(package, lib.loc = lib.loc, character.only = TRUE, logical.return = TRUE,  :
    # there is no package called ‘time’
    
  2. 在这种情况下,lapply() 调用返回并打印的列表对象没有意义,因此将输出设置为不可见是有意义的。假设你在使用 R Notebook 进行分析工作,使用 invisible() 函数将抑制列表对象的内容,并防止渲染的笔记本文件中出现混乱。


1
谢谢您。在Rmd中,我设置include=F来删除@daroczig解决方案中杂乱的TRUE输出列表,但添加invisible()是与笔记本无关的,所以您的添加更好。 - Dylan_Gomes

20

对于想要同时安装和加载软件包的人,我发现了这个函数,来自于这个链接

# ipak function: install and load multiple R packages.
# check to see if packages are installed. Install them if they are not, then load them into the R session.

ipak <- function(pkg){
new.pkg <- pkg[!(pkg %in% installed.packages()[, "Package"])]
if (length(new.pkg)) 
    install.packages(new.pkg, dependencies = TRUE)
sapply(pkg, require, character.only = TRUE)
}

# usage
packages <- c("ggplot2", "plyr", "reshape2", "RColorBrewer", "scales", "grid")
ipak(packages)

你好,我从你提供的片段创建了一个R文件。 当我在Amazon EMR服务上运行该脚本时,它会给我以下输出, 如下URL所指定的。 http://pastie.org/10402378#3,10-11,13。 - Rubin Porwal

10

另一个选项来自于包easypackages(需要安装)。您可以以最直观的方式加载包:

library("easypackages")
libraries("plyr", "psych", "tm")

这个套餐还包括一个安装多个包的函数:

packages("plyr", "psych", "tm")

参考此处


函数名相当令人困惑。“library”在library函数中指的是安装软件包的位置:软件包库。通过libraries加载多个软件包毫无意义。拥有一个执行其他操作的单独函数packages只会让情况更糟。我知道在软件工程中命名是一个难题,但这些名称真的很糟糕。 - Konrad Rudolph
5
我不同意@KonradRudolph的观点,认为“libraries”这个名字是有道理的。它是“library”的复数形式,“library”加载单个包;“libraries”则加载多个包。如果你把“library”理解为“从单个库加载”,并将其扩展到“libraries”表示“从多个库加载”,那么它可能不直观,但这并不是设计意图;我对“libraries”这个名称感到很满意。 - Jamie S
1
@JamieS 但它仍然(通常)从单个库加载。您似乎混淆了库和包(这在R中已经很普遍了):“R库”,如我之前的评论所述,是指安装R包的位置(目录/目录)。在此答案的示例中,“plyr”、“psych”和“tm”不是库:它们是包。 - Konrad Rudolph

6
你可以简单地使用lubripack包,它能整洁地安装新的包,然后在一行中加载它们所有。
lubripack("plyr", "psych", "tm")

在RStudio中运行上述代码后,以下是输出结果。

enter image description here

如何安装软件包:

运行以下代码从GitHub下载并安装软件包。无需拥有GitHub帐户。

library(devtools)
install_github("espanta/lubripack")

5
我猜测使用图像而不是文本。 - The Unfun Cat
4
这个回答并没有给出之前未回答的问题,看起来更像是自我推销。 - Tyler Rinker
你说得对,我试图隐含地回答问题。让我们明确地表达,希望它能成为问题的答案。 - Espanta
@TylerRinker 现在怎么样了? - Espanta

3

在daroczig的解决方案基础上,如果您不想指定一个列表作为输入,则可以使用

# Foo
mLoad <- function(...) {
  sapply(sapply(match.call(), as.character)[-1], require, character.only = TRUE)
}

# Example 
mLoad(plyr, dplyr, data.table)

...比...短

lapply(list('plyr', 'dplyr', 'data.table'), require, character.only = TRUE)

2

对 Tyler Rinker 的答案进行了轻微修改,添加了一个检查以安装和加载 pacman:

#Install/load pacman
if(!require(pacman)){install.packages("pacman");require(pacman)}
#Install/load tons of packages
p_load(plyr,psych,tm)

我喜欢p_load方案,因为它避免了引用!原始回答。

2

I use the following function:

mrip <- function(..., install = TRUE){
    reqFun <- function(pack) {
        if(!suppressWarnings(suppressMessages(require(pack, character.only = TRUE)))) {
            message(paste0("unable to load package ", pack,
                           ": attempting to download & then load"))
            install.packages(pack)
            require(pack, character.only = TRUE)
        }
    }
    lapply(..., reqFun)
}

这个操作会尝试加载内容,如果失败则安装并再次尝试加载。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接