439

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.

Is there an elegant way to call installed.packages(), compare that to the ones I am loading and install if missing?

Jaap
  • 81,064
  • 34
  • 182
  • 193
Maiasaura
  • 32,226
  • 27
  • 104
  • 108
  • 1
    @krlmlr What about the accepted answer is out of date and requires revision? It works for me (for a few quick tests) under `R version 3.0.2 (2013-09-25) x86_64-w64-mingw32/x64 (64-bit)`. – Brian Diggs Nov 07 '13 at 21:47
  • 1
    @BrianDiggs: At least three packages have appeared that address this problem, only one is referenced below. Is there even more -- that's the question. – krlmlr Nov 07 '13 at 22:09
  • 3
    @krlmlr There seems to be a bit of an ironic chicken-and-egg problem about using a package to ensure (others) have necessary packages. But certainly worth having someone who knows about them write up an answer. – Brian Diggs Nov 07 '13 at 23:20
  • 2
    @BrianDiggs: Bootstrapping this installation-checking package is a necessary nuisance, but a small one. Unless, of course, the functionality finds its way into `base`... ;-) – krlmlr Nov 07 '13 at 23:25
  • 1
    Coming from Node.js, it is insane how hard this is. How is this not a first class function of the language? – mel May 25 '21 at 08:30

34 Answers34

402

Yes. If you have your list of packages, compare it to the output from installed.packages()[,"Package"] and install the missing packages. 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.

Shane
  • 98,550
  • 35
  • 224
  • 217
  • 16
    I think the proper syntax is: `if(length(new.packages)>0) {install.packages(new.packages)}` –  Aug 14 '15 at 10:16
  • 8
    @psql , Shine is right, since ">0" is "implicit" within the if condition. run this for to verify it: `new.packages <- c(1,2)` `length(new.packages)` `if(length(new.packages)){print("hello!")}else{print("oh no!")}` – Andrea Cirillo Jan 22 '16 at 07:57
  • 9
    The doc of installed.packages states: "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)..." – Thomas Materna May 11 '16 at 15:01
  • 2
    Agree with Thomas, this would be better performance with `require` instead of checking `installed.packages` – Matthew Jun 20 '17 at 18:55
  • 1
    `packrat` was made for this. It is a reproducible package management system. This way is going about it the wrong way and messes with someone else's environment and not reproducible. Packrat has it own folder and environment for the shared libraries. https://rstudio.github.io/packrat/ – mtelesha Nov 02 '17 at 19:07
  • 1
    `packrat` is going to be one big mess if you have many packages in your project though. – vladli Oct 17 '18 at 07:37
  • 1
    Can't say this is elegant. can cause RStudio to crash if the library list is big. – HoofarLotusX Feb 05 '19 at 03:25
  • i've added this to the top of my source and i get the error, "could not find function "installed.packages" " Does anyone have leads on this? – MadmanLee Jun 12 '19 at 23:00
  • if the list.of.packages contains packages from both CRAN and Bioconductor, how to work with it? thanks a lot! @shane – Jiang Liang Nov 24 '19 at 16:19
  • I have created a loop based on this answer, I hope it helps: `if(length(new.packages) > 0) {install.packages(new.packages, dependencies = TRUE) print(paste0("The following package was installed:", new.packages)) } else if (length(new.packages) == 0) {print("All packages were already installed previously")}` – RodLL Jan 05 '21 at 11:45
  • Just upgraded ```R``` to version 4.1.2 and ```RStudio``` to to 2021.09.1 Build 372 on macOS 10.15.7 and although the packages I need are indeed not installed, variable ```new.packages``` throws ```character(0)```. I tried to update manually all the packages, to no avail. Any ideas on what changed and what to do? – pdeli Nov 18 '21 at 18:12
311

Dason K. and I have the pacman package that can do this nicely. The function p_load in the package does this. The first line is just to ensure that pacman is installed.

if (!require("pacman")) install.packages("pacman")
pacman::p_load(package1, package2, package_n)
Tyler Rinker
  • 108,132
  • 65
  • 322
  • 519
89

You can just use the return value of 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. 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.

Livius
  • 3,240
  • 1
  • 17
  • 28
  • 7
    You can simplify your life a lot by using `character.only = TRUE` in `require`, but then I guess there is nothing to differentiate your answer from mine. – Simon O'Hanlon Nov 09 '13 at 14:00
  • This looks nice but it doesn't seem to work, at least for me. When I tried the robust version of this, I get two error messages as R doesn't know how to handle "return True" and "return eval" for some reason. So I would really like a function like this that loads a package if present in my library and otherwise installs (and afterwards loads) the package. Ideally I would then use this as a default to load packages. At least it seems it would make sense to do so and would save some time. – Dr. Fabian Habersack Jul 13 '19 at 13:29
49

A lot of the answers above (and on duplicates of this question) rely on installed.packages which is bad form. 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). It needs to read several files per installed package, which will be slow on Windows and on some network-mounted file systems.

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

Here's the same function but with a windows dialog that asks if the user wants to install the missing packages

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)
        }
    }
}
Matthew
  • 4,149
  • 2
  • 26
  • 53
  • 3
    This is a pretty elegant way, much better than the accepted one. I'll include it in my personal library. Thanks. – Bing Dec 02 '18 at 19:17
  • 1
    This is an elegant solution. One thing though: `winDialog()` is platform specific and limited to Windows only. – Pål Bjartan Apr 26 '23 at 21:50
40
if (!require('ggplot2')) install.packages('ggplot2'); library('ggplot2')

"ggplot2" is the package. 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.

mpalanco
  • 12,960
  • 2
  • 59
  • 67
user6784955
  • 401
  • 4
  • 2
34

TL;DR you can use find.package() for this.

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.

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
  • 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. 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. 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.

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:

# 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. 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').

MichaelChirico
  • 33,841
  • 14
  • 113
  • 198
  • 1
    Well researched answer! Nevertheless I was a bit puzzled by the ambiguous return: `file.exists(file.path(.libPaths(), 'sf', 'DESCRIPTION')) [1] TRUE FALSE`. Should I just go with the first bool when designing a package installation chain? – saQuist Oct 07 '21 at 08:49
  • 1
    @saQuist yes, IINM that's what install.packages does. actually it's probably more like a for loop, looping over the .libPaths() and exiting once success – MichaelChirico Oct 07 '21 at 15:43
24

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 returns (invisibly) a logical indicating whether the required package is available

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" ) )
Simon O'Hanlon
  • 58,647
  • 14
  • 142
  • 184
  • Wouldn't you want to call `require` again after installing? – krlmlr Nov 08 '13 at 23:22
  • @krlmlr Nope, because in order for the `if` statement to be evaluated it must first evaluate `require`, the side-effect of which is loading the package if it is available! – Simon O'Hanlon Nov 08 '13 at 23:26
  • 1
    SimonO101: I think krlmlr means in the if statement, after the call to `install.packages`, as this wouldn't actually load that package. But (to @krlmlr) I suspect the intent is that this code fragment would only be called once; you wouldn't write this every time you required the package. Instead you'd run it once ahead of time and then call `require` as usual as needed. – Aaron left Stack Overflow Nov 09 '13 at 02:53
  • @Aaron ah yes ok, I see what you mean, and yes your interpretation is correct. I'll edit it slightly to be more explicit about loading after installing. – Simon O'Hanlon Nov 09 '13 at 09:52
  • Is it possible that the definition of you own `R` function doesn't work when you run the script from the `shell`? – MERose Feb 05 '15 at 16:00
  • 1
    wouldn't it be better to make the second `require` a call to `library` so that it fails noisily if it is still unable to attach the package for some reason? – kabdulla Nov 10 '16 at 04:12
16

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)
    }
}
15
# 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)
Brian Spiering
  • 1,002
  • 1
  • 9
  • 18
  • 2
    This is the best answer in my option. It allows for multiple packages to be installed, but only installs those that are not already installed. – mikey Jul 30 '21 at 17:02
8

Use packrat so that the shared libraries are exactly the same and not changing other's environment.

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. It is developed by RStudio by Hadley Wickham. 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 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/

Community
  • 1
  • 1
mtelesha
  • 2,079
  • 18
  • 16
7

This is the purpose of the rbundler package: to provide a way to control the packages that are installed for a specific project. Right now the package works with the devtools functionality to install packages to your project's directory. The functionality is similar to Ruby's bundler.

If your project is a package (recommended) then all you have to do is load rbundler and bundle the packages. The bundle function will look at your package's DESCRIPTION file to determine which packages to bundle.

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

Now the packages will be installed in the .Rbundle directory.

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

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

Here's the github repo for the project if you're interested in contributing: rbundler.

Erik Shilts
  • 4,389
  • 2
  • 26
  • 51
7

You can simply use the setdiff function to get the packages that aren't installed and then install them. In the sample below, we check if the ggplot2 and Rcpp packages are installed before installing them.

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())))
Alex Essilfie
  • 12,339
  • 9
  • 70
  • 108
  • I use the same approach. We can also use `installed.packages()[,'Package']` instead of `rownames(installed.packages())`. – Scudelletti May 23 '17 at 14:52
7

The current version of RStudio (>=1.2) includes a feature to detect missing packages in library() and require() calls, and prompts the user to install them:

Detect missing R packages

Many R scripts open with calls to library() and require() to load the packages they need in order to execute. 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. No more typing install.packages() repeatedly until the errors go away!
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:

Many of them are novice/intermediate R users and don't realize that they have to install packages they don't already have.

Aurèle
  • 12,545
  • 1
  • 31
  • 49
6

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.

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.

Dirk Eddelbuettel
  • 360,940
  • 56
  • 644
  • 725
5

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)

Anish Sugathan
  • 389
  • 4
  • 4
5

I use following function to install package if require("<package>") exits with package not found error. It will query both - CRAN and Bioconductor repositories for missing package.

Adapted from the original work by 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. This can take a long time and consider it as a full R upgrade which may not be warranted all the time!

Samir
  • 724
  • 10
  • 18
  • It could be improved by checking if packages are actually avilable on cran or bc. Also it should use library at the end to throw an error if the installation failed or a package does not exist. See my improved version called `loadpack()` on https://raw.githubusercontent.com/holgerbrandl/datautils/master/R/core_commons.R – Holger Brandl May 12 '16 at 09:45
5

Today, I stumbled on two handy function provided by the rlang package, namely, is_installed() and 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. 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.

Created on 2022-03-25 by the reprex package (v2.0.1)

hplieninger
  • 3,214
  • 27
  • 32
3

I have implemented the function to install and load required R packages silently. 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);
Pratik Patil
  • 3,662
  • 3
  • 31
  • 31
3

Quite basic one.

pkgs = c("pacman","data.table")
if(length(new.pkgs <- setdiff(pkgs, rownames(installed.packages())))) install.packages(new.pkgs)
jangorecki
  • 16,384
  • 4
  • 79
  • 160
3

Thought I'd contribute the one I use:

testin <- function(package){if (!package %in% installed.packages())    
install.packages(package)}
testin("packagename")
Ben
  • 2,308
  • 2
  • 18
  • 25
2

Regarding your main objective " to install libraries they don't already have. " and regardless of using " instllaed.packages() ". The following function mask the original function of require. It tries to load and check the named package "x" , if it's not installed, install it directly including dependencies; and lastly load it normaly. you rename the function name from 'require' to 'library' to maintain integrity . 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")

Michael Petrotta
  • 59,888
  • 27
  • 145
  • 179
GeoObserver
  • 128
  • 6
  • If you don't like your answer anymore, don't vandalize it - just delete it. – Michael Petrotta Nov 17 '13 at 02:42
  • Well, I tried , but i couldn't. I think my NoScript extension of FF is disabling it or I don't have the rights and credits to delete my own answer. LoL However, I think Livius is quite near to my answer, thought without masking. Thanks Michael Petrotta. for the notification. – GeoObserver Nov 18 '13 at 09:44
  • You should see a `delete` link above these comments. If you don't, and you still want to delete, use the `flag` link, select "other", and explain to a moderator that you'd like the answer removed. – Michael Petrotta Nov 18 '13 at 16:04
2
 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 }
ruemorgue
  • 39
  • 4
2
source("https://bioconductor.org/biocLite.R")
if (!require("ggsci")) biocLite("ggsci")
Shicheng Guo
  • 1,233
  • 16
  • 19
2

Using lapply family and anonymous function approach you may:

  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.
  4. Print each package final load status (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 
    
George Shimanovsky
  • 1,668
  • 1
  • 17
  • 15
1

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, ])
}
metasequoia
  • 7,014
  • 5
  • 41
  • 54
1

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)
Phantom Photon
  • 768
  • 2
  • 10
  • 20
1
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)

s n
  • 21
  • 2
1

In my case, I wanted a one liner that I could run from the commandline (actually via a Makefile). Here is an example installing "VGAM" and "feather" if they are not already installed:

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:

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

teichert
  • 3,963
  • 1
  • 31
  • 37
1

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))) 
lf_araujo
  • 1,991
  • 2
  • 16
  • 39
1

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, i.e., the end-state is the same regardless of starting state. 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).

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.

1

Is really nobody using librarian?

# install.packages("librarian") # install if you do not have it
librarian::shelf(Rcpp, tidyverse/ggplot2)

As you can see it even can install from github without quotation marks making it more consistent. Furthermore, it can install bioconductor packages.

Johannes Titz
  • 972
  • 6
  • 11
0
  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)
}
KVemuri
  • 194
  • 1
  • 16
0
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)
}
Nad Pat
  • 3,129
  • 3
  • 10
  • 20
0

Standing on the shoulders of @MichaelChirico:

stopifnot(3 == length(find.package(c('foo', 'bar', 'baz'))))
DomQ
  • 4,184
  • 38
  • 37