2

I'm attempting to package my software in a way that it will sense whether the pack is present and then install it if not. For example below I take advantage of logical.return within the library function. The reason for this is my code is starting to spread over the world and i would like it to automatically install the necessary packages so that the user does not have to deal with the error when the package is not present.

This set of code is written at the top of all the functions I want to import.

What I envisioned is that this set of code would install the package if it was not present. Yet this set of code does not act as i expected.

My first question is how to specify my CRAN mirror before i execute the code below.

My second question is there a better way to accomplish this?

if( !library(reticulate, logical.return = T) ){
    install.packages('reticulate');library(reticulate)
}
if( !library(png, logical.return = T) ){
    install.packages('png');library(png)
}
if( !library(RColorBrewer, logical.return = T) ){
    install.packages('RColorBrewer');library(RColorBrewer)
}
MadmanLee
  • 478
  • 1
  • 5
  • 18

1 Answers1

2

I usually do something like this:

library(utils) #needed for the source to load installed.packages()
options(repos=c("https://cran.rstudio.com", getOption("repos") ) )
## designate packages to install/load
all_pkgs <- c("reticulate","png","RColorBrewer")
## find packages that need to be installed
already_installed <- rownames(installed.packages())
to_install <- setdiff(all_pkgs, already_installed)
if (length(to_install) > 0) {
    install.packages(to_install, dependencies=TRUE)
}
## now load all packages
sapply(all_pkgs, library, character.only=TRUE, logical.return=TRUE)

Note that it's not universally considered good practice to auto-install packages: what if a user doesn't have network access, or has expensive network access and wants to choose whether to download packages, etc. ?

Note that one of the answers to the linked duplicate points out that using install.packages() to check whether a particular (small) set of packages is already installed is inefficient: this may or may not be a practical problem depending on context.

MadmanLee
  • 478
  • 1
  • 5
  • 18
Ben Bolker
  • 211,554
  • 25
  • 370
  • 453
  • Hi ben. I preferred your method more than the other answers. One thing to note is that to utilize this within a source file it is important to explicitly load the 'utils', otherwise this will not autoload. I have added this to your answer. In addition to your comment about allowing users to choose what to load and what not, this option is great for making a set of functions work immediately without a new user troublshooting. – MadmanLee Jun 18 '19 at 17:18