优雅的方式来检查丢失的包并安装它们?

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

有没有一个优雅的方式来调用installed.packages() ,比较到我正在加载和安装,如果丢失?

是。 如果您有软件包列表,请将其与installed.packages()[,"Package"]的输出进行比较,然后安装缺less的软件包。 像这样的东西:

 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) 

除此以外:

如果你把你的代码放在一个包中,并且使它们依赖,那么当你安装你的包时,它们将自动被安装。

Dason K.和我有pacman包,可以很好地做到这一点。 包中的函数p_load执行此操作。 第一行是确保安装pacman。

 if (!require("pacman")) install.packages("pacman") pacman::p_load(package1, package2, package_n) 

你可以使用require的返回值:

 if(!require(somepackage)){ install.packages("somepackage") library(somepackage) } 

我在安装之后使用library ,因为如果安装不成功或者由于其他原因无法加载软件包,则会引发exception。 你可以使这个更强大和可重用:

 dynamic_require <- function(package){ if(eval(parse(text=paste("require(",package,")")))) return True install.packages(package) return eval(parse(text=paste("require(",package,")"))) } 

这种方法的缺点是你必须把包名称放在引号中,而你并不require这么做。

尽pipeShane的答案确实不错,但对于我的一个项目,我需要删除输出消息,警告并自动安装包。 我终于设法得到这个脚本:

 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) } } 

此解决scheme将采用包名称的字符向量并尝试加载它们,或者在加载失败时安装它们。 它依赖于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" ) ) 
 # 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) 

当然。

您需要比较“已安装的软件包”和“所需的软件包”。 这与我使用CRANberries所做的非常接近,因为我需要将“存储已知软件包”与“当前已知软件包”进行比较,以确定新的和/或更新的软件包。

所以做一些像

 AP <- available.packages(contrib.url(repos[i,"url"])) # available t repos[i] 

获取所有已知的包,对当前安装的包进行模拟调用,并将其与给定的一组目标包进行比较。

这是rbundler软件包的目的:提供一种方法来控制为特定项目安装的软件包。 现在,该软件包可以与devtoolsfunction一起使用,将软件包安装到您的项目目录中。 这个function类似于Ruby的捆绑器 。

如果你的项目是一个包(推荐),那么你所要做的就是加载rbundler并捆绑包。 bundle函数将查看你的包的DESCRIPTION文件来确定捆绑哪些包。

 library(rbundler) bundle('.', repos="http://cran.us.r-project.org") 

现在这些包将被安装在.Rbundle目录中。

如果你的项目不是一个包,那么你可以通过在你的项目的根目录下创build一个DESCRIPTION文件来伪造它,并且用Depends字段来列出你想要安装的包(带有可选的版本信息):

 Depends: ggplot2 (>= 0.9.2), arm, glmnet 

如果你对贡献感兴趣的话,这里是项目的github回购: rbundler 。

上面的许多答案(和这个问题的重复)依赖于installed.packages是不好的forms。 从文档:

如果安装了数千个软件包,这可能会很慢,所以不要使用它来查找是否安装了命名软件包(使用system.file或find.package),也不知道软件包是否可用(请求require并检查返回值)也不能查找less量包的细节(使用packageDescription)。 它需要为每个已安装的软件包读取多个文件,而在Windows和某些networking安装的文件系统上,这些文件会很慢。

因此,更好的方法是尝试使用require加载包,如果加载失败则安装(如果未find,则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") 

这样它会加载所有的软件包,然后返回并安装所有缺less的软件包(如果你愿意的话,是一个方便的地方插入一个提示,询问用户是否想安装软件包)。 不要为每个包分别调用install.packages ,而是只传递一次卸载的整个包。

这里有相同的function,但有一个窗口对话框,询问用户是否要安装缺less的软件包

 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) } } } 

如果require("<package>")出现包未find错误,我使用下面的函数来安装包。 它将同时查询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)biocLite(character(), ask=FALSE)将更新系统上所有已安装的软件包。 这可能需要很长时间,并认为这是一个完整的R升级,这可能不是所有的时间!

您可以简单地使用setdiff函数来获取未安装的软件包,然后安装它们。 在下面的示例中,我们检查在安装ggplot2Rcpp包之前是否安装了它们。

 unavailable <- setdiff(c("ggplot2", "Rcpp"), rownames(installed.packages())) install.packages(unavailable) 

在一行中,上面可以写成:

 install.packages(setdiff(c("ggplot2", "Rcpp"), rownames(installed.packages()))) 
 if (!require('ggplot2')) install.packages('ggplot2'); library('ggplot2') 

“ggplot2”是包。 它会检查包是否已安装,如果没有安装。 然后加载这个包,不pipe它使用哪个分支。

以下简单的function就像一个魅力:

  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) } 

(不是我的,在networking上发现这个在一段时间后,一直使用它,不知道原始来源)

我已经实现了安装和加载所需的R软件包的function。 希望可能有帮助。 这里是代码:

 # 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); 

关于你的主要目标是“安装他们还没有安装的库”,而不pipe用“instllaed.packages()”。 以下function掩盖了require的原始function。 它试图加载和检查命名包“x”,如果没有安装,直接安装包括依赖项; 并最后加载它normaly。 您将函数名称从“require”重命名为“library”以保持完整性。 唯一的限制是应该引用包名。

 require <- function(x) { if (!base::require(x, character.only = TRUE)) { install.packages(x, dep = TRUE) ; base::require(x, character.only = TRUE) } } 

所以你可以加载和安装包的旧时尚方式R. require(“ggplot2”)require(“Rcpp”)

我使用下面这将检查是否安装包,如果依赖关系更新,然后加载包。

 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, ]) } 

这是我的代码:

 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) 
  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 } 

相当基本的一个。

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

以为我会贡献一个我使用的:

 testin <- function(package){if (!package %in% installed.packages()) install.packages(package)} testin("packagename") 
 library <- function(x){ x = toString(substitute(x)) if(!require(x,character.only=TRUE)){ install.packages(x) base::library(x,character.only=TRUE) }} 

这与未引用的包名称一起使用,并且相当优雅(参考GeoObserver的答案)

在优雅和最佳实践方面,我认为你从根本上走错了方向。 包装包是为这些问题devise的。 它由Hadley Wickham的RStudio开发。 Intesad他们必须安装依赖关系,并可能弄乱别人的系统packrat使用自己的目录,并安装程序的所有依赖关系,并不会触及某人的环境。

Packrat是R的依赖pipe理系统。

R包依赖可能令人沮丧。 你有没有必要使用试错法来找出你需要安装哪些R包来使别人的代码工作,然后永远留下这些包在全局安装,因为现在你不知道你是否需要它们? 你有没有更新过一个包,以获得你的项目中的代码工作,只是发现更新的软件包使另一个项目中的代码停止工作?

我们build立了包装解决这些问题。 使用packrat使您的R项目更多:

  • 隔离:为一个项目安装新的或更新的软件包不会破坏其他项目,反之亦然。 这是因为packrat为每个项目提供了自己的私有包库。
  • 便携式:轻松地将您的项目从一台计算机传输到另一台计算机,即使跨越不同的平台 Packrat可以轻松安装您的项目所依赖的软件包。
  • 可重复性:Packratlogging您所依赖的确切软件包版本,并确保无论您身在何处都可以安装这些精确版本。

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

 source("https://bioconductor.org/biocLite.R") if (!require("ggsci")) biocLite("ggsci") 

尝试这个:

 if (!require(MyDesiredLibrary)) { install.packages("MyDesiredLibrary") }