Automatic Installation from DESCRIPTION

Hey all, this is more a general R question than Rstudio, but I'm trying to figure out if a function exists (in base R or a package) that will automate package installation, given a DESCRIPTION file.

What I mean is something like pip install -r requirements.txt -c constraints.txt for Python, or Julia's ]instantiate. Starting from a barebones R install, this instantiate("./DESCRIPTION") or whatever would automatically install everything in Depends: and Imports:, have a flag to also install Suggests:, and would take care of getting the versions right (both > and <) where specified.

I've been searching for a while now and haven't found anything, but the terms are so general I'm not sure if I might have just missed it.

Thanks!

1 Like

I'm not quite sure how what you're asking for is different to install.packages(), possible with the dependencies argument set to which dependencies you want it to install.

This, of course, assumes you're installing directly from CRAN, but I think that would have you covered. I'm not quite clear on how your use case differs from installing a packages as per normal.

The desire is to only have the DESCRIPTION file: for a package, a repo full of notebooks, or just one made from scratch, and to do all the installs automatically so that R is ready to go, simply by providing only that file to this theoretical function. I don't want a human to have to parse a package list out of the file, figure out any versioning, or make any decision aside from whether or not to install Suggests.

If install.packages() can do this, that's not clear to me from the docs—I only know of passing it a c() of package names.

1 Like

So, having just done a tiny bit of testing, I think you can use a DESCRIPTION file in your project, and then "install" your project using devtools::install().

E.g. I added a DESCRIPTION file to a project, adding a package I knew I didn't have installed to the DESCRIPTION and called devtools::install() on it. The missing dependency got installed along with "installing" the project.

However, I'm not sure this is a good idea (I suspect it's not), as my project isn't actually a package, and in the long run this might cause me some problems. The first one I can think of is that this will potentially overwrite already installed packages if you call for specific versions of a package to run your project with.

If you're trying to capture the dependencies of a particular project you might get some value from looking at renv, the new dependency management system that RStudio have put/are putting together: https://rstudio.github.io/renv/index.html (just on GitHub for now, but I think a CRAN release is imminent looking at their NEWS file).

1 Like

I'd recommend the function install_deps() from the package remotes. Given the path to a directory that contains an R package (i.e. a DESCRIPTION file), it will install (or update) only those package dependencies that are not already available. This is an advantage over install.packages(), which will re-install the packages you request even if the latest version is already available on your machine.

1 Like

An update to my previous suggestion to use remotes::install_deps(). It's not as sophisticated as I had thought. It doesn't respect the versions specified in DESCRIPTION. If upgrade = TRUE (or you interactively agree to upgrade), it will install the latest version available. Otherwise, it will not change the version of the package if it is already installed. Futhermore, it will never downgrade to an older version (e.g. if you set a maximum version in your DESCRIPTION like knitr (<= 1.18) and knitr 1.25 is currently installed).

This is similar behavior to install.packages(), which does not even update packages if the DESCRIPTION files specifies a version greater than the one currently installed. From ?install.packages:

You are advised to run update.packages before install.packages to ensure that any already installed dependencies have their latest versions.

Therefore if you want behavior similar to pip install -r requirements.txt where you can pin exact versions of packages, you'll need to use a package manager such as packrat, renv, conda, etc.

I think renv is the way to go here. packrat has been essentially deprecated in favour of renv (I think), and I've not heard of anyone having a good experience using conda environments for managing R packaging.

1 Like

In my opinion, it depends on the nature of the project. packrat is stable, whereas renv isn't even on CRAN yet. If you want stability, go with packrat. If you want the bleeding edge, and don't mind potential breaking changes in the API, go with renv.

Well now you have. :slight_smile: If you only have R dependencies, then it makes sense to use an R-specific package manager. But my bioinformatics projects tend to include R, Python, and command-line programs (C, C++, Java, etc), and this is where using a multi-lingual package manager like conda pays off. Sure it has its quirks and conventions that you have to learn, but building all your software from source is painful.

Thanks for the responses. They helped me realize that for now I can just use install_local() for now to get something like what I need. Guess I may have to write my own parser to have it fully obey version directives.

Hopefully renv takes off. Should make this stuff easier in the future, at least.

1 Like