最近我似乎和合作者分享了很多代码。他们中的许多人是新手/中级R用户,并没有意识到他们必须安装他们还没有的包。
是否有一种优雅的方式来调用installed.packages(),比较那些我正在加载和安装如果丢失?
最近我似乎和合作者分享了很多代码。他们中的许多人是新手/中级R用户,并没有意识到他们必须安装他们还没有的包。
是否有一种优雅的方式来调用installed.packages(),比较那些我正在加载和安装如果丢失?
是的。如果您有软件包列表,请将其与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)
否则:
如果您将代码放在包中并使它们成为依赖项,那么当您安装包时,它们将自动安装。
确定。
您需要比较“已安装的包”和“所需的包”。这非常接近于我用蔓越莓做的事情,因为我需要比较“存储的已知包”和“当前已知的包”,以确定新的和/或更新的包。
就像这样
AP <- available.packages(contrib.url(repos[i,"url"])) # available t repos[i]
为了获得所有已知的包,模拟调用当前安装的包,并将其与给定的目标包集进行比较。
虽然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)
}
Use:
libraries <- c("ReadImages", "ggplot2")
for(library in libraries)
{
if(!UsePackage(library))
{
stop("Error!", library)
}
}
我使用以下将检查包是否安装和依赖项是否更新,然后加载包。
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, ])
}
这就是rbundler包的目的:提供一种方法来控制为特定项目安装的包。现在,这个包使用devtools功能将包安装到项目的目录中。该功能类似于Ruby的捆绑器。
如果你的项目是一个包(推荐),那么你所要做的就是加载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。
此解决方案将获取包名的字符向量并尝试加载它们,或者在加载失败时安装它们。它依赖于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" ) )
你可以使用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则不这样做。
达森·k和我有一个吃豆人包可以很好地做到这一点。包中的p_load函数执行此操作。第一行代码只是为了确保安装了pacman。
if (!require("pacman")) install.packages("pacman")
pacman::p_load(package1, package2, package_n)
关于你的主要目标“安装他们还没有的库”。并且不管使用" installed .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”)
# 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)
我已经实现了无声安装和加载所需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);
下面这个简单的函数非常好用:
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)
}
(不是我的,一段时间前在网上找到了这个,从那时起就一直在使用它。不确定原始来源)
下面是我的代码:
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)
我使用以下函数安装包,如果require("<包>")退出包未发现错误。它将查询- CRAN和Bioconductor存储库,以查找丢失的包。
改编自约书亚·威利的原著, 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
注:更新。packages(ask =FALSE) & biocLite(character(), ask=FALSE)将更新系统上所有已安装的软件包。这可能需要很长时间,并将其视为一个完整的R升级,这可能并不总是有保障的!
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")
您可以简单地使用setdiff函数获取未安装的包,然后安装它们。在下面的示例中,我们在安装ggplot2和Rcpp包之前检查它们是否已经安装。
unavailable <- setdiff(c("ggplot2", "Rcpp"), rownames(installed.packages()))
install.packages(unavailable)
在一行中,上面的内容可以写成:
install.packages(setdiff(c("ggplot2", "Rcpp"), rownames(installed.packages())))
library <- function(x){
x = toString(substitute(x))
if(!require(x,character.only=TRUE)){
install.packages(x)
base::library(x,character.only=TRUE)
}}
这适用于不带引号的包名,并且相当优雅(参见GeoObserver的答案)
if (!require('ggplot2')) install.packages('ggplot2'); library('ggplot2')
“ggplot2”是包。它检查包是否安装,如果没有安装,就安装它。然后不管它采用哪个分支,它都会加载包。
使用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/
上面的许多答案(以及这个问题的副本)依赖于安装。包装是不好的形式。从文档中可以看到:
当安装了数千个包时,这可能会很慢,所以不要使用它来查找是否安装了指定的包(使用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)
}
}
}
source("https://bioconductor.org/biocLite.R")
if (!require("ggsci")) biocLite("ggsci")
在我的例子中,我想要一个可以从命令行(实际上是通过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)。
使用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(点播)}) 心理学 真真真真
当前版本的RStudio(>=1.2)包含了一个功能,可以检测library()和require()调用中缺失的包,并提示用户安装它们:
检测丢失的R包 许多R脚本打开时调用library()和require()来加载执行所需的包。如果您打开一个R脚本,该脚本引用了您没有安装的包,RStudio现在将提供一次单击即可安装所有所需的包。不再重复输入install.packages(),直到错误消失! https://blog.rstudio.com/2018/11/19/rstudio-1-2-preview-the-little-things/
这似乎很好地解决了OP最初的问题:
他们中的许多人是新手/中级R用户,并没有意识到他们必须安装他们还没有的包。
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)
}
让我分享一点疯狂:
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)))
你可以使用find.package()。
这里几乎所有的答案都依赖于(1)require()或(2)installed.packages()来检查给定的包是否已经安装。
我添加了一个答案,因为这些对于回答这个问题的轻量级方法来说是不令人满意的。
Require具有加载包的名称空间的副作用,这可能并不总是可取的 安装。Packages是点燃蜡烛的火箭筒——它将首先检查所有已安装的包,然后我们检查这个库中是否有一个(或几个)包“库存”。没有必要为了找一根针而堆一堆干草堆。
这个答案也是受到@ArtemKlevtsov的启发,以类似的精神回答了这个问题的复制版本。他指出system.file(package=x)可以达到预期的效果,即返回“如果包未安装,则返回nchar > 1”。
如果我们深入了解系统。File实现了这个,我们可以看到它使用了不同的基函数find。包,我们可以直接使用:
# 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中查看引擎盖下的内容。包来看看它是如何工作的,但这主要是一个有指导意义的练习——我看到的唯一简化函数的方法是跳过一些健壮性检查。但是基本的想法是:在. libpaths()中查找——任何安装的包pkg将在file.path(. libpaths (), pkg)处有一个DESCRIPTION文件,因此快速检查file.exists(file.path(. libpaths (), pkg, 'DESCRIPTION')。
pckg=c("shiny","ggplot2","dplyr","leaflet","lubridate","RColorBrewer","plotly","DT","shinythemes")
for(i in 1:length(pckg))
{
print(pckg[i])
if (!is.element(pckg[i], installed.packages()[,1]))
install.packages(pckg[i], dep = TRUE)
require(pckg[i], character.only = TRUE)
}
有一个新的包(我是一个联合开发人员),Require,它是可复制工作流的一部分,这意味着函数在第一次运行或后续运行时产生相同的输出,也就是说,无论开始状态如何,最终状态都是相同的。下面安装任何缺失的包(我包含require = FALSE以严格解决最初的问题…通常我把这个设置为默认值,因为我通常希望它们加载到搜索路径)。
这两行位于我编写的每个脚本的顶部(根据需要调整包的选择),允许任何人在任何条件下(包括任何或所有依赖项缺失)使用脚本。
if (!require("Require")) install.packages("Require")
Require::Require(c("ggplot2", "Rcpp"), require = FALSE)
因此,您可以在脚本中使用它或将其传递给任何人。
今天,我偶然发现了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)
站在@MichaelChirico的肩膀上:
stopifnot(3 == length(find.package(c('foo', 'bar', 'baz'))))