这些天我似乎与共同作者分享了很多代码。他们中的许多人都是初级/中级R用户,并没有意识到他们必须安装他们尚未拥有的软件包。
是否有一种优雅的方式来调用installed.packages()
,将其与我正在加载的那些进行比较,如果丢失则进行安装?
答案 0 :(得分:244)
是。如果您有包列表,请将其与installed.packages()[,"Package"]
的输出进行比较,然后安装缺少的包。像这样:
list.of.packages <- c("ggplot2", "Rcpp")
new.packages <- list.of.packages[!(list.of.packages %in% installed.packages()[,"Package"])]
if(length(new.packages)) install.packages(new.packages)
否则:
如果您将代码放在一个软件包中并使它们成为依赖项,那么在安装软件包时它们将自动安装。
答案 1 :(得分:186)
Dason K.我有 pacman 包可以很好地做到这一点。包中的函数p_load
执行此操作。第一行是为了确保安装pacman。
if (!require("pacman")) install.packages("pacman")
pacman::p_load(package1, package2, package_n)
答案 2 :(得分:56)
您可以使用require
的返回值:
if(!require(somepackage)){
install.packages("somepackage")
library(somepackage)
}
我在安装后使用library
因为如果安装不成功或者由于某些其他原因无法加载包,它将抛出异常。您可以使其更加强大和可重复使用:
dynamic_require <- function(package){
if(eval(parse(text=paste("require(",package,")")))) return True
install.packages(package)
return eval(parse(text=paste("require(",package,")")))
}
此方法的缺点是您必须在引号中传递包名称,而不是真正的require
。
答案 3 :(得分:17)
此解决方案将采用包名称的字符向量并尝试加载它们,或者在加载失败时安装它们。它依赖于require
的返回行为来执行此操作,因为......
require
返回(无形)一个逻辑,指示所需的包是否可用
因此,我们可以简单地看看我们是否能够加载所需的包,如果没有,请安装依赖项。所以给定一个你希望加载的包的字符向量...
foo <- function(x){
for( i in x ){
# require returns TRUE invisibly if it was able to load package
if( ! require( i , character.only = TRUE ) ){
# If package was not able to be loaded then re-install
install.packages( i , dependencies = TRUE )
# Load package after installing
require( i , character.only = TRUE )
}
}
}
# Then try/install packages...
foo( c("ggplot2" , "reshape2" , "data.table" ) )
答案 4 :(得分:15)
虽然Shane的答案非常好,但对于我的一个项目,我需要删除输出消息,警告并自动安装软件包 。我终于设法得到了这个脚本:
InstalledPackage <- function(package)
{
available <- suppressMessages(suppressWarnings(sapply(package, require, quietly = TRUE, character.only = TRUE, warn.conflicts = FALSE)))
missing <- package[!available]
if (length(missing) > 0) return(FALSE)
return(TRUE)
}
CRANChoosen <- function()
{
return(getOption("repos")["CRAN"] != "@CRAN@")
}
UsePackage <- function(package, defaultCRANmirror = "http://cran.at.r-project.org")
{
if(!InstalledPackage(package))
{
if(!CRANChoosen())
{
chooseCRANmirror()
if(!CRANChoosen())
{
options(repos = c(CRAN = defaultCRANmirror))
}
}
suppressMessages(suppressWarnings(install.packages(package)))
if(!InstalledPackage(package)) return(FALSE)
}
return(TRUE)
}
使用:
libraries <- c("ReadImages", "ggplot2")
for(library in libraries)
{
if(!UsePackage(library))
{
stop("Error!", library)
}
}
答案 5 :(得分:13)
上面的许多答案(以及此问题的重复)都依赖于installed.packages
,这是一种糟糕的形式。来自文档:
当安装了数千个软件包时,这可能会很慢,所以不要使用它来查明是否安装了命名软件包(使用system.file或find.package),也不知道软件包是否可用(call require)并检查返回值),也无需查找少量软件包的详细信息(使用packageDescription)。它需要为每个已安装的软件包读取多个文件,这在Windows和某些网络安装的文件系统上会很慢。
因此,更好的方法是尝试使用require
加载包,并在加载失败时安装(如果找不到,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.packages
,而是只传递一次卸载包的整个向量。
这里有相同的功能,但有一个Windows对话框,询问用户是否要安装缺少的软件包
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)
}
}
}
答案 6 :(得分:13)
if (!require('ggplot2')) install.packages('ggplot2'); library('ggplot2')
&#34; GGPLOT2&#34;是包。它会检查软件包是否已安装,如果不安装软件包。然后无论采用哪个分支,它都会加载包。
答案 7 :(得分:8)
# List of packages for session
.packages = c("ggplot2", "plyr", "rms")
# Install CRAN packages (if not already installed)
.inst <- .packages %in% installed.packages()
if(length(.packages[!.inst]) > 0) install.packages(.packages[!.inst])
# Load packages into session
lapply(.packages, require, character.only=TRUE)
答案 8 :(得分:6)
这是rbundler package的目的:提供一种控制为特定项目安装的软件包的方法。现在,该软件包与devtools功能一起使用,可以将软件包安装到项目的目录中。该功能类似于Ruby的bundler。
如果您的项目是一个软件包(推荐),那么您所要做的就是加载rbundler并捆绑软件包。 bundle
函数将查看您的包的DESCRIPTION
文件,以确定要捆绑的包。
library(rbundler)
bundle('.', repos="http://cran.us.r-project.org")
现在软件包将安装在.Rbundle目录中。
如果您的项目不是软件包,那么您可以通过在项目的根目录中创建一个DESCRIPTION
文件并使用Depends字段列出要安装的软件包(带有可选的版本信息)来伪造它:
Depends: ggplot2 (>= 0.9.2), arm, glmnet
如果您对贡献感兴趣,请参阅以下项目的github回购:rbundler。
答案 9 :(得分:5)
不确定。
您需要将“已安装的软件包”与“所需的软件包”进行比较。这与我对CRANberries的处理非常接近,因为我需要将“存储的已知包”与“当前已知的包”进行比较,以确定新的和/或更新的包。
所以做一些像
这样的事情AP <- available.packages(contrib.url(repos[i,"url"])) # available t repos[i]
获取所有已知的包,对当前安装的包进行类似调用,并将其与给定的一组目标包进行比较。
答案 10 :(得分:5)
这里几乎所有答案都取决于(1)require()
或(2)installed.packages()
来检查给定软件包是否已安装。
我要添加一个答案,因为对于采用轻量级方法来回答此问题而言,这些方法并不令人满意。
require
的副作用是加载程序包的名称空间,这可能并不总是令人满意的installed.packages
是一个点燃蜡烛的火箭筒-它会首先检查已安装软件包的宇宙,然后我们检查一个(或几个)软件包是否为“此库中的“库存”。无需为了寻找针头而建干草堆。 @ArtemKlevtsov's great answer对此问题的重复版本也以类似的精神启发了这个答案。他指出,system.file(package=x)
可能会产生预期的效果,如果未安装该软件包,则返回''
,否则返回nchar > 1
。
如果我们看看system.file
是如何做到这一点的,我们会发现它使用了另一个base
函数find.package
,我们可以直接使用它:
# a package that exists
find.package('data.table', quiet=TRUE)
# [1] "/Library/Frameworks/R.framework/Versions/4.0/Resources/library/data.table"
# a package that does not
find.package('InstantaneousWorldPeace', quiet=TRUE)
# character(0)
我们也可以在find.package
的内部进行查看,以了解其工作原理,但这主要是一个指导性练习-缩小我所看到的功能的唯一方法是跳过一些健壮性检查。但是基本的想法是:在.libPaths()
中查找-任何已安装的软件包pkg
在DESCRIPTION
处都有一个file.path(.libPaths(), pkg)
文件,因此,快速检查是{{ 1}}。
答案 11 :(得分:4)
以下简单功能就像魅力一样:
usePackage<-function(p){
# load a package if installed, else load after installation.
# Args:
# p: package name in quotes
if (!is.element(p, installed.packages()[,1])){
print(paste('Package:',p,'Not found, Installing Now...'))
install.packages(p, dep = TRUE)}
print(paste('Loading Package :',p))
require(p, character.only = TRUE)
}
(不是我的,不久之后在网上发现这个并且从那时起一直在使用它。不确定原始来源)
答案 12 :(得分:4)
如果require("<package>")
退出且找不到包错误,我使用以下函数来安装包。它将查询 - CRAN和Bioconductor存储库以查找缺失的包。
改编自Joshua Wiley的原创作品, http://r.789695.n4.nabble.com/Install-package-automatically-if-not-there-td2267532.html
install.packages.auto <- function(x) {
x <- as.character(substitute(x))
if(isTRUE(x %in% .packages(all.available=TRUE))) {
eval(parse(text = sprintf("require(\"%s\")", x)))
} else {
#update.packages(ask= FALSE) #update installed packages.
eval(parse(text = sprintf("install.packages(\"%s\", dependencies = TRUE)", x)))
}
if(isTRUE(x %in% .packages(all.available=TRUE))) {
eval(parse(text = sprintf("require(\"%s\")", x)))
} else {
source("http://bioconductor.org/biocLite.R")
#biocLite(character(), ask=FALSE) #update installed packages.
eval(parse(text = sprintf("biocLite(\"%s\")", x)))
eval(parse(text = sprintf("require(\"%s\")", x)))
}
}
示例:
install.packages.auto(qvalue) # from bioconductor
install.packages.auto(rNMF) # from CRAN
PS:update.packages(ask = FALSE)
&amp; biocLite(character(), ask=FALSE)
将更新系统上所有已安装的软件包。这可能需要很长时间,并将其视为完整的R升级,可能无法保证!
答案 13 :(得分:4)
您只需使用setdiff
函数即可获取尚未安装的软件包,然后再安装它们。在下面的示例中,我们会检查是否安装了 ggplot2
和 Rcpp
包。
unavailable <- setdiff(c("ggplot2", "Rcpp"), rownames(installed.packages()))
install.packages(unavailable)
在一行中,上述内容可写为:
install.packages(setdiff(c("ggplot2", "Rcpp"), rownames(installed.packages())))
答案 14 :(得分:3)
我已经实现了以静默方式安装和加载所需R包的功能。希望可能有帮助。这是代码:
# Function to Install and Load R Packages
Install_And_Load <- function(Required_Packages)
{
Remaining_Packages <- Required_Packages[!(Required_Packages %in% installed.packages()[,"Package"])];
if(length(Remaining_Packages))
{
install.packages(Remaining_Packages);
}
for(package_name in Required_Packages)
{
library(package_name,character.only=TRUE,quietly=TRUE);
}
}
# Specify the list of required packages to be installed and load
Required_Packages=c("ggplot2", "Rcpp");
# Call the Function
Install_And_Load(Required_Packages);
答案 15 :(得分:3)
使用packrat
,以便共享库完全相同,而不会改变其他人的环境。
在优雅和最佳实践方面,我认为你从根本上讲是错误的。包packrat
是针对这些问题而设计的。它由Htley Wickham的RStudio开发。而不是他们必须安装依赖项并可能搞砸某人环境系统packrat
使用自己的目录并在其中安装程序的所有依赖项,并且不会触及某人的环境。
Packrat是R。
的依赖管理系统R包依赖可能令人沮丧。您是否曾经不得不使用反复试验来确定需要安装哪些R软件包才能使其他人的代码正常工作 - 然后将这些软件包永久保留在全局安装,因为现在您不确定是否需要它们?你有没有更新过一个软件包来获取你的一个项目中的代码,只是发现更新的软件包使另一个项目中的代码停止工作?
我们建立了packrat来解决这些问题。使用packrat使您的R项目更多:
- 隔离:为一个项目安装新的或更新的包不会破坏您的其他项目,反之亦然。那是因为packrat为每个项目提供了自己的私有包库。
- 便携式:轻松将您的项目从一台计算机传输到另一台计算机,甚至跨越不同的平台。 Packrat使您可以轻松安装项目所依赖的软件包。
- 可重复:Packrat会记录您所依赖的确切软件包版本,并确保无论您走到哪里都可以安装这些版本。
答案 16 :(得分:2)
相当基本的一个。
pkgs = c("pacman","data.table")
if(length(new.pkgs <- setdiff(pkgs, rownames(installed.packages())))) install.packages(new.pkgs)
答案 17 :(得分:2)
以为我会贡献我使用的那个:
testin <- function(package){if (!package %in% installed.packages())
install.packages(package)}
testin("packagename")
答案 18 :(得分:2)
关于你的主要目标“安装他们还没有的库。”而不管使用“instllaed.packages()”。以下函数掩盖了require的原始函数。它尝试加载并检查命名包“x”,如果没有安装,直接安装它包括依赖项;并最后正常加载它。您将函数名称从'require'重命名为'library'以保持完整性。唯一的限制是应该引用包名称。
require <- function(x) {
if (!base::require(x, character.only = TRUE)) {
install.packages(x, dep = TRUE) ;
base::require(x, character.only = TRUE)
}
}
所以你可以加载和安装R的旧时尚方式 要求(“ggplot2”) 要求(“Rcpp”)
答案 19 :(得分:2)
使用lapply家族和匿名函数方法,您可以:
||
惰性评估)。打印每个包装的最终装载状态(TRUE
/ FALSE
)。
req <- substitute(require(x, character.only = TRUE))
lbs <- c("plyr", "psych", "tm")
sapply(lbs, function(x) eval(req) || {install.packages(x); eval(req)})
plyr psych tm
TRUE TRUE TRUE
答案 20 :(得分:1)
我使用以下内容检查是否已安装软件包以及是否更新了依赖项,然后加载软件包。
p<-c('ggplot2','Rcpp')
install_package<-function(pack)
{if(!(pack %in% row.names(installed.packages())))
{
update.packages(ask=F)
install.packages(pack,dependencies=T)
}
require(pack,character.only=TRUE)
}
for(pack in p) {install_package(pack)}
completeFun <- function(data, desiredCols) {
completeVec <- complete.cases(data[, desiredCols])
return(data[completeVec, ])
}
答案 21 :(得分:1)
让我有一点疯狂:
c("ggplot2","ggsci", "hrbrthemes", "gghighlight", "dplyr") %>% # What will you need to load for this script?
(function (x) ifelse(t =!(x %in% installed.packages()),
install.packages(x[t]),
lapply(x, require)))
答案 22 :(得分:1)
即将发布的RStudio(1.2)版本将提供预览功能,该功能将包含一项功能,可检测到<VALUES>
<VALUE>example</VALUE>
<VALUE>example1</VALUE>
<VALUE>good,example</VALUE>
<VALUE>test</VALUE>
<VALUES>
和library()
调用中缺少的软件包,并提示用户安装它们:>
检测缺少的R包
打开许多R脚本,它们调用
require()
和library()
来加载执行它们所需的包。如果您打开一个R脚本,该脚本引用了尚未安装的软件包,则RStudio现在将提供单击安装所有所需软件包的功能。在错误消失之前,不再需要重复输入require()
!
https://blog.rstudio.com/2018/11/19/rstudio-1-2-preview-the-little-things/
这似乎很好地解决了OP最初的担忧:
他们中的许多人是R新手/中级用户,他们没有意识到他们必须安装尚未拥有的软件包。
答案 23 :(得分:1)
source("https://bioconductor.org/biocLite.R")
if (!require("ggsci")) biocLite("ggsci")
答案 24 :(得分:1)
library <- function(x){
x = toString(substitute(x))
if(!require(x,character.only=TRUE)){
install.packages(x)
base::library(x,character.only=TRUE)
}}
这适用于不带引号的包名称并且相当优雅(参见GeoObserver的回答)
答案 25 :(得分:1)
48 lapply_install_and_load <- function (package1, ...)
49 {
50 #
51 # convert arguments to vector
52 #
53 packages <- c(package1, ...)
54 #
55 # check if loaded and installed
56 #
57 loaded <- packages %in% (.packages())
58 names(loaded) <- packages
59 #
60 installed <- packages %in% rownames(installed.packages())
61 names(installed) <- packages
62 #
63 # start loop to determine if each package is installed
64 #
65 load_it <- function (p, loaded, installed)
66 {
67 if (loaded[p])
68 {
69 print(paste(p, "loaded"))
70 }
71 else
72 {
73 print(paste(p, "not loaded"))
74 if (installed[p])
75 {
76 print(paste(p, "installed"))
77 do.call("library", list(p))
78 }
79 else
80 {
81 print(paste(p, "not installed"))
82 install.packages(p)
83 do.call("library", list(p))
84 }
85 }
86 }
87 #
88 lapply(packages, load_it, loaded, installed)
89 }
答案 26 :(得分:1)
这是我的代码:
packages <- c("dplyr", "gridBase", "gridExtra")
package_loader <- function(x){
for (i in 1:length(x)){
if (!identical((x[i], installed.packages()[x[i],1])){
install.packages(x[i], dep = TRUE)
} else {
require(x[i], character.only = TRUE)
}
}
}
package_loader(packages)
答案 27 :(得分:0)
在我的情况下,我想要一个可以从命令行运行的单行程序(实际上是通过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")
除了以下解决方案之外没有任何其他解决方案:
repos
参数进行了硬编码(以避免任何弹出窗口询问镜像使用)另请注意重要的character.only=TRUE
(如果没有,require
会尝试加载包p
)。
答案 28 :(得分:0)
packages_installed <- function(pkg_list){
pkgs <- unlist(pkg_list)
req <- unlist(lapply(pkgs, require, character.only = TRUE))
not_installed <- pkgs[req == FALSE]
lapply(not_installed, install.packages,
repos = "http://cran.r-project.org")# add lib.loc if needed
lapply(pkgs, library, character.only = TRUE)
}