最近我似乎和合作者分享了很多代码。他们中的许多人是新手/中级R用户,并没有意识到他们必须安装他们还没有的包。
是否有一种优雅的方式来调用installed.packages(),比较那些我正在加载和安装如果丢失?
最近我似乎和合作者分享了很多代码。他们中的许多人是新手/中级R用户,并没有意识到他们必须安装他们还没有的包。
是否有一种优雅的方式来调用installed.packages(),比较那些我正在加载和安装如果丢失?
当前回答
在我的例子中,我想要一个可以从命令行(实际上是通过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)。
其他回答
今天,我偶然发现了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)
你可以使用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则不这样做。
虽然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)
}
}
在我的例子中,我想要一个可以从命令行(实际上是通过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)。
有一个新的包(我是一个联合开发人员),Require,它是可复制工作流的一部分,这意味着函数在第一次运行或后续运行时产生相同的输出,也就是说,无论开始状态如何,最终状态都是相同的。下面安装任何缺失的包(我包含require = FALSE以严格解决最初的问题…通常我把这个设置为默认值,因为我通常希望它们加载到搜索路径)。
这两行位于我编写的每个脚本的顶部(根据需要调整包的选择),允许任何人在任何条件下(包括任何或所有依赖项缺失)使用脚本。
if (!require("Require")) install.packages("Require")
Require::Require(c("ggplot2", "Rcpp"), require = FALSE)
因此,您可以在脚本中使用它或将其传递给任何人。