230

How can I load a bunch of packages at once with out retyping the require command over and over? I've tried three approaches all of which crash and burn.

Basically, I want to supply a vector of package names to a function that will load them.

x<-c("plyr", "psych", "tm")

require(x)
lapply(x, require)
do.call("require", x)
MBorg
  • 1,345
  • 2
  • 19
  • 38
Tyler Rinker
  • 108,132
  • 65
  • 322
  • 519

10 Answers10

316

Several permutations of your proposed functions do work -- but only if you specify the character.only argument to be TRUE. Quick example:

lapply(x, require, character.only = TRUE)
daroczig
  • 28,004
  • 7
  • 90
  • 124
  • @Tommy & daroczig -- Cool. That's a far cleaner solution. I'll leave mine up only for posterity, and for what it shows about why the OP's attempts didn't work. – Josh O'Brien Nov 18 '11 at 00:22
  • 7
    You can take advantage of the partial character matching and get away with lapply(x, require, ch = T) or even lapply(x, require, c = T) – Dason Nov 18 '11 at 04:22
  • 1
    @daroczig This code loads the packages but why does it give the following Warning messages: 1: In library(package, lib.loc = lib.loc, character.only = TRUE, logical.return = TRUE, : there is no package called ‘x’ 2: In if (!loaded) { : the condition has length > 1 and only the first element will be used – Anusha Nov 01 '12 at 13:48
  • @Anusha: I have no idea ATM, what you have in your `x`? – daroczig Nov 01 '12 at 14:54
  • @daroczig I am just running code given here. Changed do.call command to do.call("require", list(x)) otherwise it wouldnt run. If it helps, using rstudio. – Anusha Nov 01 '12 at 15:00
  • 1
    @Anusha: I must miss something obvious, but I have never typed `do.call` in my answer, so I am a bit puzzled about your reply. – daroczig Nov 01 '12 at 15:36
  • @daroczig Sorry. I thought you were adding character.only=T to the code given in question. And the next answer by Josh also included the do.call command. Maybe an edit can clarify for other readers. – Anusha Nov 01 '12 at 16:03
  • @daroczig: can this be extended, adding a install call of any missing packages from the list provided by x? – Paulo E. Cardoso Feb 19 '13 at 13:11
  • @PauloCardoso: sure, but that might be longer then a one-liner :) Basically you should check the returned value of `require` and run `install.packages` if that results to `FALSE`, and `require` again. Please open a new question (and possibly link here) if you'd get stuck. – daroczig Feb 19 '13 at 15:26
  • @daroczig: thanks. I think this would do the job: new.packs <- packs[!(packs %in% installed.packages()[,"Package"])] if(length(new.packs)) install.packages(new.packs) lapply(new.packages, require, character.only=T). Combining your and Shane example from [here](http://stackoverflow.com/questions/4090169/elegant-way-to-check-for-missing-packages-and-install-them?lq=1) – Paulo E. Cardoso Feb 20 '13 at 14:41
  • 1
    @PauloCardoso: that's right. Although I would have thought rather something like `lapply(x, function(x) {if (!require(x, character.only=T)) {install.packages(x);require(x)}})` to save any prior checks and do the install stuff only on demand. If we specify a list of packages to be loaded (and installed if needed) in `x` character - just like the OP asked. But it's getting pretty long to develop this further in a comment :) – daroczig Feb 20 '13 at 19:28
  • 34
    Be nice if R::base added this `lapply` trick native to `library()`. Be great to be able say: `library(c("plyr", "umx"))` – tim Jun 28 '15 at 18:56
86

The CRAN package pacman that I maintain (authored with Dason Kurkiewicz) can accomplish this:

So the user could do:

## install.packages("pacman")
pacman::p_load(dplyr, psych, tm) 

and if the package is missing p_load will download it from CRAN or Bioconductor.

Tyler Rinker
  • 108,132
  • 65
  • 322
  • 519
  • 9
    +1! Why did you choose the short name `p_load`? A more descriptive name such as `load_packages` makes the intent of the function more clear. – Paul Hiemstra Jan 12 '14 at 13:27
  • 24
    Because the p stands for package. Every function in the package that is useful and exported starts with `p_`. Plus we tend to use library a bit and that's an additional 7 characters. 7 characters x ~1000000 life time uses of the function x .5 seconds per character = 3500000 seconds. That's 58333.33 minutes, 972.2222 hours or 40.50926 days of a programmer's life we've given back to them :-) In any event our goal is to push to CRAN by Feb 1 – Tyler Rinker Jan 12 '14 at 13:44
  • 4
    About a year late but we finally submitted to CRAN. Should be up in a few days. @trinker (or me) make sure to modify this once it goes public. – Dason Feb 15 '15 at 01:06
  • 6
    @Tyler I know I’m years late but I find your rationale for the `p_` prefix rather dubious. If terseness is the issue, remove the `p_` prefix entirely. In fact, having such prefixes are generally discouraged in other languages for good reasons (I’ve told Hadley they same with regards to his `fct_` nonsense in forcats). This is *especially* true since the intended usage of th package is with a qualified namespace (`pacman::`). – Konrad Rudolph Feb 22 '17 at 23:36
  • 1
    @KonradRudolph I can see the point but there are already many functions in common R packages including base packages with those names. This guards against namespace conflicts. You point out that I use the `pacman::` but it's silly to believe everyone will use a package in the way I do. Like most everything there is a tradeoff. Here the tradeoff is terseness vs. descriptiveness vs. namespace conflicts. Plus at this point a change like this would break too many people's code. – Tyler Rinker Feb 23 '17 at 15:37
  • 5
    @TylerRinker Apologies for being combative on this issue, but I truly think that the R community is simply wrong here, and virtually every other modern language gets it right: You say “This guards against namespace conflicts.” — But *this is what namespaces are for!* The onus on package writers is to educate people to use the packages properly, not to accommodate their sloppy programming practices. – Konrad Rudolph Feb 23 '17 at 16:20
  • 2
    Cool! I guess this solves questions https://stackoverflow.com/q/9341635/1169233 and https://stackoverflow.com/q/4090169/1169233 (I see you've posted an answer to the latter, but not to the former, which is closed anyway). – Waldir Leoncio Feb 08 '18 at 08:17
  • @TylerRinker, thanks a lot for the convenient solution - is there also a way to use `p_load()` on a string vector of packages, say `pks <- c("devtools", "tidyverse")`? – Ivo Nov 12 '19 at 08:43
  • 2
    @Ivo `character.only = TRUE` or `p_load(char = pks)` – Tyler Rinker Nov 12 '19 at 14:15
  • [This approach](https://www.mitchelloharawild.com/blog/loading-r-packages-in-a-loop/) from Mitchell O'Hara-Wild is useful – p0bs Jun 28 '21 at 15:13
25

This should do the trick:

lapply(x, FUN = function(X) {
    do.call("require", list(X)) 
})

(The key bit is that the args argument in do.call(what, args) must be a list --- even if it only has a single element!)

Josh O'Brien
  • 159,210
  • 26
  • 366
  • 455
20

I think the code that @daroczig has provided can be improved by replacing the require with library and wrapping the lapply call inside the invisible() function. So, the improved code will look like the following:

invisible(lapply(x, library, character.only = TRUE))

This code is improved because:

  1. library() is generally preferred over require() for loading packages because the former gives an error if the package is not installed while the latter just gives a warning. Moreover, require() calls library(), so why not just use library() directly!

    library("time")
    # Error in library("time") : there is no package called ‘time’
    
    require("time")
    # Loading required package: time
    # Warning message:
    # In library(package, lib.loc = lib.loc, character.only = TRUE, logical.return = TRUE,  :
    # there is no package called ‘time’
    
  2. The list object returned and printed by the lapply() call is not meaningful in this case, so it makes sense to make the output invisible. Say you use R Notebook for your analysis work, using the invisible() function will suppress the contents of the list object and prevent the clutter in the rendered notebook file.

Ashirwad
  • 1,890
  • 1
  • 12
  • 14
  • 1
    Thanks for this. In Rmd I set `include=F` for this code chunk to remove the messy list of `TRUE` outputs from the @daroczig solution, but adding `invisible()` is notebook agnostic, so your addition is preferred. – Dylan_Gomes Oct 13 '22 at 16:05
19

For someone who wants to install and load packages simultaneously I came across this function from this link

# ipak function: install and load multiple R packages.
# check to see if packages are installed. Install them if they are not, then load them into the R session.

ipak <- function(pkg){
new.pkg <- pkg[!(pkg %in% installed.packages()[, "Package"])]
if (length(new.pkg)) 
    install.packages(new.pkg, dependencies = TRUE)
sapply(pkg, require, character.only = TRUE)
}

# usage
packages <- c("ggplot2", "plyr", "reshape2", "RColorBrewer", "scales", "grid")
ipak(packages)
NelsonGon
  • 13,015
  • 7
  • 27
  • 57
bala
  • 553
  • 4
  • 7
  • Hello I created a R file from your given snippet. When I run that script on Amazon EMR service it gives me following output as specified in following URL. http://pastie.org/10402378#3,10-11,13. – Rubin Porwal Sep 07 '15 at 07:07
10

An alternative option comes from the package easypackages (requires installation). You can load packages in the most intuitive way:

library("easypackages")
libraries("plyr", "psych", "tm")

The package also includes a function to install several packages:

packages("plyr", "psych", "tm")

Reference here.

luchonacho
  • 6,759
  • 4
  • 35
  • 52
  • The function name is rather confusing/confused. “library”, in the `library` function, refers to the location where packages are installed: the *package library*. Loading several packages via `libraries` makes no sense. Having a separate function `packages` that does something else just makes this worse. I know naming is a hard problem in software engineering but really. These names are particularly bad. – Konrad Rudolph Feb 22 '17 at 23:40
  • 5
    @KonradRudolph I disagree that the name `libraries` makes no sense. It's the plural of `library`, and `library` loads a single package; `libraries` loads a plurality of packages. If you think of `library` as meaning "load from your single library", and extend that to `libraries` meaning "load from multiple libraries", then it's perhaps unintuitive, but that's not the intent; I would be quite happy with the name `libraries`. – Jamie S Oct 03 '18 at 16:44
  • 1
    @JamieS But it’s *still* (usually) loading from a single library. You seem to confuse library and package (which, to be fair, has become common in R): The “R library”, as my previous comment stated, refers to the location(s) (directory/directories) where R packages are installed. In this answer’s example, “plyr”, “psych” and “tm” are *not* libraries: they are packages. – Konrad Rudolph Oct 03 '18 at 21:50
6

You can simply use lubripack package and it neatly installs new packages and then load all of them in one line.

lubripack("plyr", "psych", "tm")

Here is the output after you run above code in RStudio.

enter image description here

How to Install Package:

Run below code to download the package and install it from GitHub. No need to have GitHub Account.

library(devtools)
install_github("espanta/lubripack")
David Arenburg
  • 91,361
  • 17
  • 137
  • 196
Espanta
  • 1,080
  • 1
  • 17
  • 27
3

Building on daroczig's solution, if you do not want to specify a list as input you can use

# Foo
mLoad <- function(...) {
  sapply(sapply(match.call(), as.character)[-1], require, character.only = TRUE)
}

# Example 
mLoad(plyr, dplyr, data.table)

... which is shorter than

lapply(list('plyr', 'dplyr', 'data.table'), require, character.only = TRUE)
goclem
  • 904
  • 1
  • 10
  • 21
2

I use the following function:

mrip <- function(..., install = TRUE){
    reqFun <- function(pack) {
        if(!suppressWarnings(suppressMessages(require(pack, character.only = TRUE)))) {
            message(paste0("unable to load package ", pack,
                           ": attempting to download & then load"))
            install.packages(pack)
            require(pack, character.only = TRUE)
        }
    }
    lapply(..., reqFun)
}

This tries to load, and if it fails installs and then try to load again.

ricardo
  • 8,195
  • 7
  • 47
  • 69
2

Slight mod of Tyler Rinker's answer to add a check to install & load pacman:

#Install/load pacman
if(!require(pacman)){install.packages("pacman");require(pacman)}
#Install/load tons of packages
p_load(plyr,psych,tm)

I like the p_load solution because it avoids quoting!

mattador
  • 421
  • 4
  • 12