优雅的方式来检查丢失的包并安装它们?
我似乎现在和共同作者分享了很多代码。 他们中的许多人是新手/中级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
函数来获取未安装的软件包,然后安装它们。 在下面的示例中,我们检查在安装ggplot2
和Rcpp
包之前是否安装了它们。
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您所依赖的确切软件包版本,并确保无论您身在何处都可以安装这些精确版本。
source("https://bioconductor.org/biocLite.R") if (!require("ggsci")) biocLite("ggsci")
尝试这个:
if (!require(MyDesiredLibrary)) { install.packages("MyDesiredLibrary") }