Chances are you often need to use more than one package in R, so it is common to see that an R script starts with multiple calls to library()
, the function that attaches a package to an R session, e.g.,
library(ggplot2)
library(dplyr)
library(shiny)
The vectorized library()
With the function xfun::pkg_attach()
, you can attach them through a character vector:
xfun::pkg_attach(c('ggplot2', 'dplyr', 'shiny'))
As I said in a post on “library()
vs require()
” in 2014, I believe it was a design mistake to use NSE (non-standard evaluation) in library()
. It saves a little bit typing effort since you don’t need to type the quotes, but it also opens a can of worms, and introduces more non-standard things due to this non-standard thing (e.g., when you do code analysis, you have to make a special rule for the library()
calls to make sure those “variables” in parentheses are not real variables but character strings of package names). The above xfun::pkg_attach()
call is essentially a for-loop:
for (i in c('ggplot2', 'dplyr', 'shiny')) {
library(i, character.only = TRUE)
}
Automatically install missing packages
It is also common to see code like this in R scripts (install a package if not installed or loadable):
if (!require('shiny')) install.packages('shiny')
library(shiny)
if (!require('ggplot2')) install.packages('ggplot2')
library(ggplot2)
The argument install = TRUE
in xfun::pkg_attach()
allows you to do the above task, e.g.,
xfun::pkg_attach(c('ggplot2', 'dplyr', 'shiny'), install = TRUE)
Or use the shorthand xfun::pkg_attach2()
, which is essentially pkg_attach(..., install = TRUE)
:
xfun::pkg_attach2(c('ggplot2', 'dplyr', 'shiny'))
Some people may argue that you should never install software packages without the user’s permission. That is a good point. If your R script is meant to be run by other users, you need to be a little conservative, but some users may actually prefer convenience (i.e., don’t bother me with error messages about missing packages). Of course, if you are writing a script for yourself, you can always use pkg_attach2()
. If you want to ask for permission, you certainly can, e.g.,
xfun::pkg_attach(
c('ggplot2', 'dplyr', 'shiny'),
install = readline('Install missing packages (y/n)? ') == 'y'
)
Suppress package startup messages
Some people don’t like package startup messages. I think those messages are fine if they only appear once or at most a couple of times to a new user. When you see the same messages over and over again, you will be bored, but you cannot shout at your screen that “I KNOW dplyr::filter()
MASKS stats::filter()
! PLEASE DON’T TELL ME THIS AGAIN!” when you library(tidyverse)
.
How to suppress package startup messages? As you could have guessed, the function is named suppressPackageStartupMessages()
. Do you like it? I don’t, because it is too long and often calls for disproportional attention when you read the code (worse if you have to call it multiple times). Do I have a better name? No (so I’ll shut up on naming).
If you are attaching a package in knitr, you can use the chunk option message = FALSE
to suppress package startup messages, e.g.,
```{r, message=FALSE}
library(tidyverse)
```
Note that this will suppress any types of messages, including package startup messages. It might be a problem, but I often load packages in a separate code chunk in the beginning of a knitr document, so it is unlikely to suppress messages that I didn’t mean to suppress.
Since my colleague Winston was not satisfied by this solution, I added a message
argument to xfun::pkg_attach()
to suppress startup messages (and he didn’t like it, either, which was understandable).
xfun::pkg_attach('tidyverse', message = FALSE)
The default value of message
in this function comes from the global option xfun.pkg_attach.message
, so you may set it in your .Rprofile
to always suppress startup messages, e.g.,
options(xfun.pkg_attach.message = FALSE)
I wish the library()
function has a similar argument, so I don’t have to hack at it this way.
Will xfun::pkg_attach()
become the new library()
?
No, I don’t believe so, and I don’t mean so, either. I wrote this post just to illustrate one type of pain I mentioned a few days ago: the pain that is tiny yet comes frequently. To sum it up, the tiny pain here is:
-
You cannot
library(c('ggplot2', 'dplyr', 'shiny'))
. -
You have to test the availability of a package explicitly before deciding to install it, i.e.,
if (!require()) install.packages()
. -
You have to explicitly suppress the package startup messages every single time if you don’t want to see them, either through a long-named function or by a knitr chunk option.