简体   繁体   English

检查丢失的软件包并安装它们的优雅方法?

[英]Elegant way to check for missing packages and install them?

I seem to be sharing a lot of code with coauthors these days.这些天,我似乎与合著者共享了很多代码。 Many of them are novice/intermediate R users and don't realize that they have to install packages they don't already have.他们中的许多人是新手/中级 R 用户,并且没有意识到他们必须安装他们还没有的软件包。

Is there an elegant way to call installed.packages() , compare that to the ones I am loading and install if missing?有没有一种优雅的方式来调用installed.packages() ,将其与我正在加载和安装的那些进行比较(如果丢失)?

Yes.是的。 If you have your list of packages, compare it to the output from installed.packages()[,"Package"] and install the missing packages.如果您有软件包列表,请将其与installed.packages()[,"Package"]的输出进行比较并安装缺少的软件包。 Something like this:像这样的东西:

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)

Otherwise:除此以外:

If you put your code in a package and make them dependencies, then they will automatically be installed when you install your package.如果你把你的代码放在一个包中并使它们依赖,那么当你安装你的包时它们会自动安装。

Dason K. and I have the pacman package that can do this nicely. Dason K. 和我有pacman包,可以很好地做到这一点。 The function p_load in the package does this.包中的函数p_load就是这样做的。 The first line is just to ensure that pacman is installed.第一行只是为了确保安装了 pacman。

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

You can just use the return value of require :您可以只使用require的返回值:

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

I use library after the install because it will throw an exception if the install wasn't successful or the package can't be loaded for some other reason.我在安装后使用library ,因为如果安装不成功或由于其他原因无法加载包,它会抛出异常。 You make this more robust and reuseable:你使它更健壮和可重用:

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

  install.packages(package)
  return eval(parse(text=paste("require(",package,")")))
}

The downside to this method is that you have to pass the package name in quotes, which you don't do for the real require .这种方法的缺点是你必须在引号中传递包名,你不需要为真正的require这样做。

if (!require('ggplot2')) install.packages('ggplot2'); library('ggplot2')

"ggplot2" is the package. “ggplot2”是包。 It checks to see if the package is installed, if it is not it installs it.它检查包是否已安装,如果未安装,则安装它。 It then loads the package regardless of which branch it took.然后,无论它采用哪个分支,它都会加载包。

A lot of the answers above (and on duplicates of this question) rely on installed.packages which is bad form.上面的很多答案(以及这个问题的副本)都依赖于installed.packages ,这是错误的形式。 From the documentation:从文档:

This can be slow when thousands of packages are installed, so do not use this to find out if a named package is installed (use system.file or find.package) nor to find out if a package is usable (call require and check the return value) nor to find details of a small number of packages (use packageDescription).当安装了数千个包时,这可能会很慢,所以不要使用它来确定是否安装了命名包(使用 system.file 或 find.package),也不要使用它来确定包是否可用(调用 require 并检查返回值)也找不到少量包的详细信息(使用 packageDescription)。 It needs to read several files per installed package, which will be slow on Windows and on some network-mounted file systems.它需要为每个安装的包读取多个文件,这在 Windows 和某些网络安装的文件系统上会很慢。

So, a better approach is to attempt to load the package using require and and install if loading fails ( require will return FALSE if it isn't found).因此,更好的方法是尝试使用require和 install 加载包,如果加载失败(如果找不到,则require将返回FALSE )。 I prefer this implementation:我更喜欢这个实现:

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

which can be used like this:可以这样使用:

using("RCurl","ggplot2","jsonlite","magrittr")

This way it loads all the packages, then goes back and installs all the missing packages (which if you want, is a handy place to insert a prompt to ask if the user wants to install packages).通过这种方式,它加载所有包,然后返回并安装所有丢失的包(如果需要,这是一个方便的地方,可以插入询问用户是否要安装包的提示)。 Instead of calling install.packages separately for each package it passes the whole vector of uninstalled packages just once.它不是为每个包单独调用install.packages ,而是只传递一次已卸载包的整个向量。

Here's the same function but with a windows dialog that asks if the user wants to install the missing 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)
        }
    }
}

This solution will take a character vector of package names and attempt to load them, or install them if loading fails.此解决方案将采用包名称的字符向量并尝试加载它们,或者在加载失败时安装它们。 It relies on the return behaviour of require to do this because...它依赖于require的返回行为来执行此操作,因为...

require returns (invisibly) a logical indicating whether the required package is available require返回(不可见)一个逻辑,指示所需的包是否可用

Therefore we can simply see if we were able to load the required package and if not, install it with dependencies.因此,我们可以简单地查看是否能够加载所需的包,如果不能,则使用依赖项安装它。 So given a character vector of packages you wish to load...因此,给定要加载的包的字符向量...

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

Almost all the answers here rely on either (1) require() or (2) installed.packages() to check if a given package is already installed or not.这里几乎所有的答案都依赖于 (1) require()或 (2) installed.packages()来检查给定的包是否已经安装。

I'm adding an answer because these are unsatisfactory for a lightweight approach to answering this question.我正在添加一个答案,因为这些对于回答这个问题的轻量级方法来说并不令人满意。

  • require has the side effect of loading the package's namespace, which may not always be desirable require具有加载包命名空间的副作用,这可能并不总是可取的
  • installed.packages is a bazooka to light a candle -- it will check the universe of installed packages first, then we check if our one (or few) package(s) are "in stock" at this library. installed.packages是火箭筒光蜡烛-它会首先检查安装的软件包的宇宙,然后我们检查,如果我们的一个(或几个)包(S)是“股票”在这个库。 No need to build a haystack just to find a needle.无需为了找到一根针而建造大海捞针。

This answer was also inspired by @ArtemKlevtsov's great answer in a similar spirit on a duplicated version of this question.这个答案也受到@ArtemKlevtsov在这个问题的重复版本上以类似的精神做出的伟大回答的启发。 He noted that system.file(package=x) can have the desired affect of returning '' if the package isn't installed, and something with nchar > 1 otherwise.他指出system.file(package=x)可以在未安装包的情况下具有返回''的预期效果,否则nchar > 1

If we look under the hood of how system.file accomplishes this, we can see it uses a different base function, find.package , which we could use directly:如果我们深入了解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)

We can also look under the hood at find.package to see how it works, but this is mainly an instructive exercise -- the only ways to slim down the function that I see would be to skip some robustness checks.我们也可以在find.package了解它是如何工作的,但这主要是一个有指导意义的练习——我看到的缩小函数的唯一方法是跳过一些健壮性检查。 But the basic idea is: look in .libPaths() -- any installed package pkg will have a DESCRIPTION file at file.path(.libPaths(), pkg) , so a quick-and-dirty check is file.exists(file.path(.libPaths(), pkg, 'DESCRIPTION') .但基本思想是:查看.libPaths() -- 任何已安装的包pkg都会在file.path(.libPaths(), pkg)处有一个DESCRIPTION文件,因此快速检查是file.exists(file.path(.libPaths(), pkg, 'DESCRIPTION')

Although the answer of Shane is really good, for one of my project I needed to remove the ouput messages, warnings and install packages automagically .虽然巴蒂尔的答案是真的好,我的项目之一,我需要去掉输出中的消息,警告并自动安装软件包。 I have finally managed to get this script:我终于设法得到这个脚本:

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

Use packrat so that the shared libraries are exactly the same and not changing other's environment.使用packrat使共享库完全相同并且不会改变其他人的环境。

In terms of elegance and best practice I think you're fundamentally going about it the wrong way.在优雅和最佳实践方面,我认为您从根本上走错了路。 The package packrat was designed for these issues. packrat包就是为这些问题而设计的。 It is developed by RStudio by Hadley Wickham.它由 Hadley Wickham 的 RStudio 开发。 Instead of them having to install dependencies and possibly mess up someone's environment system, packrat uses its own directory and installs all the dependencies for your programs in there and doesn't touch someone's environment.他们不必安装依赖项并可能弄乱某人的环境系统, packrat使用自己的目录并在那里安装程序的所有依赖项,并且不会触及某人的环境。

Packrat is a dependency management system for R. Packrat 是 R 的依赖管理系统。

R package dependencies can be frustrating. R 包依赖性可能令人沮丧。 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?您是否曾经不得不使用试错法来确定需要安装哪些 R 包才能使其他人的代码正常工作——然后将这些包永久安装在全局范围内,因为现在您不确定是否需要它们? 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.我们构建了 Packrat 来解决这些问题。 Use packrat to make your R projects more:使用 packrat 使您的 R 项目更多:

  • 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.那是因为 Packrat 为每个项目提供了自己的私有包库。
  • 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. Packrat 可以轻松安装项目所依赖的包。
  • Reproducible: Packrat records the exact package versions you depend on, and ensures those exact versions are the ones that get installed wherever you go.可重现:Packrat 会记录您所依赖的确切软件包版本,并确保您无论走到哪里都可以安装这些确切版本。

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

This is the purpose of the rbundler package : to provide a way to control the packages that are installed for a specific project.这就是rbundler 包的目的:提供一种方法来控制为特定项目安装的包。 Right now the package works with the devtools functionality to install packages to your project's directory.现在,该包与 devtools 功能一起使用以将包安装到您的项目目录。 The functionality is similar to Ruby's bundler .该功能类似于 Ruby 的bundler

If your project is a package (recommended) then all you have to do is load rbundler and bundle the packages.如果您的项目是一个包(推荐),那么您所要做的就是加载 rbundler 并捆绑这些包。 The bundle function will look at your package's DESCRIPTION file to determine which packages to bundle. bundle函数将查看您的包的DESCRIPTION文件以确定要捆绑哪些包。

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

Now the packages will be installed in the .Rbundle directory.现在软件包将安装在 .Rbundle 目录中。

If your project isn't a package, then you can fake it by creating a DESCRIPTION file in your project's root directory with a Depends field that lists the packages that you want installed (with optional version information):如果您的项目不是包,那么您可以通过在项目的根目录中创建一个DESCRIPTION文件来伪造它,该文件的 Depends 字段列出了您要安装的包(带有可选的版本信息):

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

Here's the github repo for the project if you're interested in contributing: rbundler .如果您有兴趣贡献,这里是该项目的 github 存储库: rbundler

You can simply use the setdiff function to get the packages that aren't installed and then install them.您可以简单地使用setdiff函数获取未安装的包,然后安装它们。 In the sample below, we check if the ggplot2 and Rcpp packages are installed before installing them.在下面的示例中,我们在安装之前检查ggplot2Rcpp包是否已安装。

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

In one line, the above can be written as:在一行中,上面可以写成:

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

Sure.当然。

You need to compare 'installed packages' with 'desired packages'.您需要将“已安装的软件包”与“所需的软件包”进行比较。 That's very close to what I do with CRANberries as I need to compare 'stored known packages' with 'currently known packages' to determine new and/or updated packages.这与我对CRANberries所做的非常接近,因为我需要将“存储的已知包”与“当前已知的包”进行比较以确定新的和/或更新的包。

So do something like所以做类似的事情

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

to get all known packages, simular call for currently installed packages and compare that to a given set of target packages.要获取所有已知包,模拟调用当前安装的包并将其与给定的一组目标包进行比较。

The following simple function works like a charm:下面的简单函数就像一个魅力:

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

(not mine, found this on the web some time back and had been using it since then. not sure of the original source) (不是我的,前段时间在网上找到了这个,从那时起就一直在使用它。不确定原始来源)

I use following function to install package if require("<package>") exits with package not found error.如果require("<package>")退出时出现包未找到错误,我使用以下函数来安装包。 It will query both - CRAN and Bioconductor repositories for missing package.它将查询 - CRAN 和 Bioconductor 存储库以查找丢失的包。

Adapted from the original work by Joshua Wiley, http://r.789695.n4.nabble.com/Install-package-automatically-if-not-there-td2267532.html改编自 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)))
  }
}

Example:例子:

install.packages.auto(qvalue) # from bioconductor
install.packages.auto(rNMF) # from CRAN

PS: update.packages(ask = FALSE) & biocLite(character(), ask=FALSE) will update all installed packages on the system. PS: update.packages(ask = FALSE) & biocLite(character(), ask=FALSE)将更新系统上所有已安装的软件包。 This can take a long time and consider it as a full R upgrade which may not be warranted all the time!这可能需要很长时间,并将其视为完整的 R 升级,但并非一直都值得!

The coming version of RStudio (1.2), already available as a preview, will include a feature to detect missing packages in library() and require() calls, and prompt the user to install them:即将推出的 RStudio (1.2) 版本已作为预览版提供,将包含一项功能,可检测library()require()调用中丢失的包,并提示用户安装它们:

Detect missing R packages检测丢失的 R 包

Many R scripts open with calls to library() and require() to load the packages they need in order to execute.许多 R 脚本打开时会调用library()require()来加载它们执行所需的包。 If you open an R script that references packages that you don't have installed, RStudio will now offer to install all the needed packages in a single click.如果您打开一个 R 脚本,该脚本引用了您尚未安装的软件包,RStudio 现在将提供一次单击即可安装所有需要的软件包的功能。 No more typing install.packages() repeatedly until the errors go away!不再重复输入install.packages()直到错误消失!
https://blog.rstudio.com/2018/11/19/rstudio-1-2-preview-the-little-things/ https://blog.rstudio.com/2018/11/19/rstudio-1-2-preview-the-little-things/

This seems to address the original concern of OP particularly well:这似乎特别好地解决了 OP 最初的担忧:

Many of them are novice/intermediate R users and don't realize that they have to install packages they don't already have.他们中的许多人是 R 新手/中级用户,并没有意识到他们必须安装他们还没有的软件包。

I have implemented the function to install and load required R packages silently.我已经实现了静默安装和加载所需 R 包的功能。 Hope might help.希望可能会有所帮助。 Here is the code:这是代码:

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

Thought I'd contribute the one I use:以为我会贡献我使用的那个:

testin <- function(package){if (!package %in% installed.packages())    
install.packages(package)}
testin("packagename")

Today, I stumbled on two handy function provided by the rlang package, namely, is_installed() and check_installed() .今天偶然发现了 rlang package 提供的两个好用的 function ,即is_installed()check_installed()

From the help page (emphasis added):帮助页面(强调添加):

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. is_installed()不与用户交互。 It simply returns TRUE or FALSE depending on whether the packages are installed.它只是根据是否安装了软件包返回TRUEFALSE

In interactive sessions , check_installed() asks the user whether to install missing packages .交互式会话中, check_installed()询问用户是否安装缺少的软件包 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.如果 session 是非交互式的,或者如果用户选择不安装软件包,则当前评估将中止。

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.

Created on 2022-03-25 by the reprex package (v2.0.1)代表 package (v2.0.1) 于 2022 年 3 月 25 日创建

Regarding your main objective " to install libraries they don't already have. " and regardless of using " instllaed.packages() ".关于您的主要目标“安装他们还没有的库。”并且无论使用“ instllaed.packages() ”。 The following function mask the original function of require.以下函数屏蔽了 require 的原始函数。 It tries to load and check the named package "x" , if it's not installed, install it directly including dependencies;它尝试加载并检查命名包 "x" ,如果未安装,则直接安装它,包括依赖项; and lastly load it normaly.最后正常加载。 you rename the function name from 'require' to 'library' to maintain integrity .您将函数名称从 'require' 重命名为 'library' 以保持完整性。 The only limitation is packages names should be quoted.唯一的限制是包名应该被引用。

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

So you can load and installed package the old fashion way of R. require ("ggplot2") require ("Rcpp")所以你可以用旧的 R 方式加载和安装包。 require ("ggplot2") require ("Rcpp")

 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 }

Quite basic one.很基本的一个。

pkgs = c("pacman","data.table")
if(length(new.pkgs <- setdiff(pkgs, rownames(installed.packages())))) install.packages(new.pkgs)
source("https://bioconductor.org/biocLite.R")
if (!require("ggsci")) biocLite("ggsci")

Using lapply family and anonymous function approach you may:使用 lapply 系列和匿名函数方法,您可以:

  1. Try to attach all listed packages.尝试附加所有列出的包。
  2. Install missing only (using || lazy evaluation).仅安装缺失(使用||延迟评估)。
  3. Attempt to attach again those were missing in step 1 and installed in step 2.尝试再次附加在步骤 1 中丢失并在步骤 2 中安装的那些。
  4. Print each package final load status ( TRUE / FALSE ).打印每个包裹的最终加载状态 ( TRUE / FALSE )。

     req <- substitute(require(x, character.only = TRUE)) lbs <- c("plyr", "psych", "tm") sapply(lbs, function(x) eval(req) || {install.packages(x); eval(req)}) plyr psych tm TRUE TRUE TRUE

I use the following which will check if package is installed and if dependencies are updated, then loads the package.我使用以下命令检查是否安装了包以及是否更新了依赖项,然后加载包。

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

Here's my code for it:这是我的代码:

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)
library <- function(x){
  x = toString(substitute(x))
if(!require(x,character.only=TRUE)){
  install.packages(x)
  base::library(x,character.only=TRUE)
}}

This works with unquoted package names and is fairly elegant (cf. GeoObserver's answer)这适用于不带引号的包名并且相当优雅(参见 GeoObserver 的回答)

In my case, I wanted a one liner that I could run from the commandline (actually via a Makefile).就我而言,我想要一个可以从命令行运行的单行代码(实际上是通过 Makefile)。 Here is an example installing "VGAM" and "feather" if they are not already installed:如果尚未安装“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")'

From within R it would just be:在 R 中,它只是:

for (p in c("VGAM", "feather")) if (!require(p, character.only=TRUE)) install.packages(p, repos="http://cran.us.r-project.org")

There is nothing here beyond the previous solutions except that:除了以前的解决方案之外,这里没有任何东西:

  • I keep it to a single line我把它保持在一行
  • I hard code the repos parameter (to avoid any popups asking about the mirror to use)我对repos参数进行了硬编码(以避免任何弹出窗口询问要使用的镜像)
  • I don't bother to define a function to be used elsewhere我不想定义一个在别处使用的函数

Also note the important character.only=TRUE (without it, the require would try to load the package p ).还要注意重要的character.only=TRUE (没有它, require将尝试加载包p )。

Let me share a bit of madness:让我分享一点疯狂:

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

There is a new-ish package (I am a codeveloper), Require , that is intended to be part of a reproducible workflow, meaning the function produces the same output the first time it is run or subsequent times , ie, the end-state is the same regardless of starting state.有一个新的包(我是一个共同开发者), Require ,它旨在成为可重现工作流的一部分,这意味着该函数在第一次运行或后续时间时产生相同的输出,即最终状态无论起始状态如何,都是相同的。 The following installs any missing packages (I include require = FALSE to strictly address the original question... normally I leave this on the default because I will generally want them loaded to the search path).以下安装任何丢失的包(我包括require = FALSE以严格解决原始问题......通常我将其保留为默认值,因为我通常希望它们加载到搜索路径)。

These two lines are at the top of every script I write (adjusting the package selection as necessary), allowing the script to be used by anybody in any condition (including any or all dependencies missing).这两行位于我编写的每个脚本的顶部(根据需要调整包选择),允许任何人在任何情况下使用该脚本(包括缺少任何或所有依赖项)。

if (!require("Require")) install.packages("Require")
Require::Require(c("ggplot2", "Rcpp"), require = FALSE)

You can thus use this in your script or pass it anyone.因此,您可以在脚本中使用它或将其传递给任何人。

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

pckg=c("shiny","ggplot2","dplyr","leaflet","lubridate","RColorBrewer","plotly","DT","shinythemes") pckg=c("shiny","ggplot2","dplyr","leaflet","lubridate","RColorBrewer","plotly","DT","shinythemes")

for(i in 1:length(pckg)) 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)

} }

Standing on the shoulders of @MichaelChirico :站在@MichaelChirico的肩膀上:

stopifnot(3 == length(find.package(c('foo', 'bar', 'baz'))))

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM