Mai*_*ura 307 packages r r-faq
这些天我似乎与共同作者分享了很多代码.他们中的许多人都是初级/中级R用户,并没有意识到他们必须安装他们尚未拥有的软件包.
是否有一种优雅的方式来调用installed.packages()
,将其与我正在加载的那些进行比较并在安装时如果丢失?
Sha*_*ane 269
是.如果您有包列表,请将其与输出进行比较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)
Run Code Online (Sandbox Code Playgroud)
除此以外:
如果您将代码放在一个包中并使它们成为依赖项,那么在安装包时它们将自动安装.
Tyl*_*ker 203
Dason K.和我有pacman包可以做得很好.p_load
包中的功能可以做到这一点.第一行是为了确保安装pacman.
if (!require("pacman")) install.packages("pacman")
pacman::p_load(package1, package2, package_n)
Run Code Online (Sandbox Code Playgroud)
Liv*_*ius 63
你可以使用以下的返回值require
:
if(!require(somepackage)){
install.packages("somepackage")
library(somepackage)
}
Run Code Online (Sandbox Code Playgroud)
我library
在安装后使用,因为如果安装不成功或由于某些其他原因无法加载包,它将抛出异常.您可以使其更加强大和可重用:
dynamic_require <- function(package){
if(eval(parse(text=paste("require(",package,")")))) return True
install.packages(package)
return eval(parse(text=paste("require(",package,")")))
}
Run Code Online (Sandbox Code Playgroud)
这种方法的缺点是你必须在引号中传递包名,而不是真实的require
.
Sim*_*lon 18
此解决方案将采用包名称的字符向量并尝试加载它们,或者在加载失败时安装它们.它依赖于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" ) )
Run Code Online (Sandbox Code Playgroud)
Mic*_*ico 18
这里几乎所有的答案都依赖于(1)require()
或(2)installed.packages()
来检查给定的包是否已经安装。
我正在添加一个答案,因为这些对于回答这个问题的轻量级方法来说并不令人满意。
require
具有加载包命名空间的副作用,这可能并不总是可取的installed.packages
是火箭筒光蜡烛-它会检查宇宙第一安装的软件包,然后我们检查,如果我们的一个(或几个)包(S)是“股票”在这个库。无需为了找到一根针而建造大海捞针。这个答案也受到@ArtemKlevtsov在这个问题的重复版本上以类似的精神做出的伟大回答的启发。他指出,如果未安装软件包,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)
Run Code Online (Sandbox Code Playgroud)
我们也可以深入find.package
了解它是如何工作的,但这主要是一个有指导意义的练习——我看到的缩小函数的唯一方法是跳过一些健壮性检查。但基本思想是:查看.libPaths()
- 任何已安装的包pkg
都会有一个位于 的DESCRIPTION
文件file.path(.libPaths(), pkg)
,因此快速检查是file.exists(file.path(.libPaths(), pkg, 'DESCRIPTION')
.
小智 16
if (!require('ggplot2')) install.packages('ggplot2'); library('ggplot2')
Run Code Online (Sandbox Code Playgroud)
"ggplot2"是包.它会检查软件包是否已安装,如果不安装软件包.然后它加载包,无论它采用哪个分支.
Mat*_*hew 16
上面的许多答案(以及这个问题的重复)依赖于installed.packages
哪种形式不好.从文档:
当安装了数千个软件包时,这可能会很慢,所以不要使用它来查明是否安装了命名软件包(使用system.file或find.package),也不知道软件包是否可用(调用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)
}
}
Run Code Online (Sandbox Code Playgroud)
可以像这样使用:
using("RCurl","ggplot2","jsonlite","magrittr")
Run Code Online (Sandbox Code Playgroud)
这样它就可以加载所有的包,然后返回并安装所有丢失的包(如果你愿意的话,这是一个方便的地方,可以插入提示询问用户是否要安装包).它不是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)
}
}
}
Run Code Online (Sandbox Code Playgroud)
Jua*_*ano 15
虽然巴蒂尔的答案是真的好,我的项目之一,我需要去掉输出中的消息,警告并安装软件包自动的.我终于设法得到这个脚本:
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)
}
Run Code Online (Sandbox Code Playgroud)
使用:
libraries <- c("ReadImages", "ggplot2")
for(library in libraries)
{
if(!UsePackage(library))
{
stop("Error!", library)
}
}
Run Code Online (Sandbox Code Playgroud)
# 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)
Run Code Online (Sandbox Code Playgroud)
使用packrat
以便共享库完全相同并且不改变其他环境。
在优雅和最佳实践方面,我认为您从根本上走错了路。该软件包packrat
专为这些问题而设计。它由 Hadley Wickham 的 RStudio 开发。他们不必安装依赖项并可能弄乱某人的环境系统,而是packrat
使用自己的目录并在那里安装程序的所有依赖项,并且不会触及某人的环境。
Packrat 是 R 的依赖管理系统。
R 包依赖性可能令人沮丧。您是否曾经不得不使用试错法来确定需要安装哪些 R 包才能使其他人的代码正常工作——然后将这些包永久安装在全局范围内,因为现在您不确定是否需要它们? 您是否曾经更新过一个包以使您的一个项目中的代码工作,却发现更新的包使另一个项目中的代码停止工作?
我们构建了 Packrat 来解决这些问题。使用 packrat 使您的 R 项目更多:
- 隔离:为一个项目安装一个新的或更新的包不会破坏你的其他项目,反之亦然。那是因为 Packrat 为每个项目提供了自己的私有包库。
- 便携:轻松地将您的项目从一台计算机传输到另一台计算机,甚至可以跨越不同的平台。Packrat 可以轻松安装项目所依赖的包。
- 可重现:Packrat 会记录您所依赖的确切软件包版本,并确保您无论走到哪里都可以安装这些确切版本。
https://rstudio.github.io/packrat/
您可以简单地使用该setdiff
功能获取未安装的软件包,然后安装它们。在下面的示例中,我们在安装ggplot2
和Rcpp
包之前检查它们是否已安装。
unavailable <- setdiff(c("ggplot2", "Rcpp"), rownames(installed.packages()))
install.packages(unavailable)
Run Code Online (Sandbox Code Playgroud)
在一行中,上面可以写成:
install.packages(setdiff(c("ggplot2", "Rcpp"), rownames(installed.packages())))
Run Code Online (Sandbox Code Playgroud)
这是rbundler软件包的目的:提供一种控制为特定项目安装的软件包的方法.现在,该软件包与devtools功能一起使用,可以将软件包安装到项目的目录中.该功能类似于Ruby的捆绑器.
如果您的项目是一个包(推荐),那么您所要做的就是加载rbundler并捆绑包.该bundle
函数将查看包的DESCRIPTION
文件以确定要捆绑的包.
library(rbundler)
bundle('.', repos="http://cran.us.r-project.org")
Run Code Online (Sandbox Code Playgroud)
现在这些包将安装在.Rbundle目录中.
如果您的项目不是软件包,那么您可以通过DESCRIPTION
在项目的根目录中创建一个文件来伪装它,其中Depends字段列出了您要安装的软件包(带有可选的版本信息):
Depends: ggplot2 (>= 0.9.2), arm, glmnet
Run Code Online (Sandbox Code Playgroud)
如果您有兴趣贡献,那么这是该项目的github回购:rbundler.
当然.
您需要将"已安装的软件包"与"所需的软件包"进行比较.这与我对CRANberries的处理非常接近,因为我需要将"存储的已知包"与"当前已知的包"进行比较,以确定新的和/或更新的包.
所以做点什么
AP <- available.packages(contrib.url(repos[i,"url"])) # available t repos[i]
Run Code Online (Sandbox Code Playgroud)
获取所有已知的包,对当前安装的包进行类似调用,并将其与给定的一组目标包进行比较.
小智 5
下面的简单函数就像一个魅力:
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)
}
Run Code Online (Sandbox Code Playgroud)
(不是我的,前段时间在网上找到了这个,从那时起就一直在使用它。不确定原始来源)
如果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)))
}
}
Run Code Online (Sandbox Code Playgroud)
例子:
install.packages.auto(qvalue) # from bioconductor
install.packages.auto(rNMF) # from CRAN
Run Code Online (Sandbox Code Playgroud)
PS:update.packages(ask = FALSE)
&biocLite(character(), ask=FALSE)
将更新系统上所有已安装的软件包。这可能需要很长时间,并将其视为完整的 R 升级,但并非一直都值得!
即将推出的 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 的新手/中级用户,并没有意识到他们必须安装他们还没有的软件包。
今天,我偶然发现了 rlang 包提供的两个方便的函数,即is_installed()
和check_installed()
。
从帮助页面(添加了重点):
这些函数检查软件包的安装是否具有最小的副作用。如果安装,将加载包但不附加包。
is_installed()
不与用户交互。它只是返回TRUE
orFALSE
取决于是否安装了软件包。在交互式会话中,
check_installed()
询问用户是否安装缺少的软件包。如果用户接受,则会安装软件包[...]。如果会话是非交互式的或者用户选择不安装软件包,则当前评估将中止。
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.
Run Code Online (Sandbox Code Playgroud)
由reprex 包(v2.0.1)于 2022 年 3 月 25 日创建