Working With Different Versions of an R Package

Recently, I had to install an older version of an R package, because a function was deprecated that I wanted to use. I wanted to install the old version in addition to and not instead of the new version.

This post has been updated in April 2020. Previously, install_version() and install_github() had no lib argument which made it necessary to use a workaround via the withr package to install to a non-standard library. Today, these functions pass lib to install.packages(), which makes this whole endeavor a lot easier.

Installing Packages to a Custom Location

library("remotes")
library("fs")

In addition to my standard Windows library, I created two new folders to store packages, one for older packages and one for devel versions.

dev_lib <- path_home_r("R/win-library/dev-versions/")
old_lib <- path_home_r("R/win-library/old-versions/")

# dir_create(dev_lib)
# dir_create(old_lib)

The aim was to have a folder structure similar to the one shown below:

C:/Users/hp/Documents/R
└── win-library
    ├── 3.5
    ├── 3.6
    |   ├── ...
    |   ├── dplyr
    |   ├── ...
    │   ├── MplusAutomation
    |   └── ...
    ├── dev-versions
    │   └── dplyr
    └── old-versions
        └── MplusAutomation

Installing Development Packages

The remotes package has many functions to install packages from various sources. The functions in remotes used to live in the devtools package and can still be used via devtools.

Probably the function that is used most is install_github(), which I use here to install the current version of the dplyr package from https://github.com/tidyverse/dplyr/.

install_github("tidyverse/dplyr", lib = dev_lib, upgrade = "always")

Now, I can either load the CRAN version or the development version. As of this writing, the new function relocate() is not yet part of the CRAN version such that the first attempt fails.

head(iris)
#>   Sepal.Length Sepal.Width Petal.Length Petal.Width Species
#> 1          5.1         3.5          1.4         0.2  setosa
#> 2          4.9         3.0          1.4         0.2  setosa
#> 3          4.7         3.2          1.3         0.2  setosa
#> 4          4.6         3.1          1.5         0.2  setosa
#> 5          5.0         3.6          1.4         0.2  setosa
#> 6          5.4         3.9          1.7         0.4  setosa

library("dplyr")
packageVersion("dplyr")
#> [1] '0.8.5'
try(relocate(iris, Species))
#> Error in relocate(iris, Species) : could not find function "relocate"

detach("package:dplyr")

library("dplyr", lib.loc = dev_lib)
packageVersion("dplyr")
#> [1] '0.8.99.9002'
head( relocate(iris, Species) )
#>   Species Sepal.Length Sepal.Width Petal.Length Petal.Width
#> 1  setosa          5.1         3.5          1.4         0.2
#> 2  setosa          4.9         3.0          1.4         0.2
#> 3  setosa          4.7         3.2          1.3         0.2
#> 4  setosa          4.6         3.1          1.5         0.2
#> 5  setosa          5.0         3.6          1.4         0.2
#> 6  setosa          5.4         3.9          1.7         0.4

Installing Outdated Packages

remotes::install_version() allows to install an outdated version of a package automatically without having to manually download the archive.

install_version("MplusAutomation", version = "0.7", lib = old_lib)

Now, I can either load the CRAN version or the development version. In the current CRAN version, the function extractModelSummaries() is no longer available such that the first attempt fails.

suppressPackageStartupMessages(
    library("MplusAutomation")
)
packageVersion("MplusAutomation")
#> [1] '0.7.3'

MplusAutomation::extractModelSummaries()
#> extractModelSummaries has been deprecated. Please use readModels("nameofMplusoutfile.out", what="summaries")$summaries to replicate the old functionality.

detach("package:MplusAutomation")

library("MplusAutomation", lib.loc = old_lib)
packageVersion("MplusAutomation")
#> [1] '0.7'

# works with a valid target:
# MplusAutomation::extractModelSummaries(target = NULL)

Special cases

As noted above, the package withr can give you further control if that is necessary. In the original version of this blog post, I used with_libpaths(), since install_github() did not accept a lib argument in the past.

library("withr")
with_libpaths(new = dev_lib,
              code = install_github("tidyverse/dplyr",
                                    dependencies = FALSE))

Reproducibility via a Project-Specific Library

Sometimes, you want more control. You may want to specify exactly the version of an R package that should be used (e.g., dplyr 0.8.0.1). This is the time for a dependency management system that allows you to have project-specific libraries. In R, this is best managed by means of the packrat package or its successor, the renv package.


comments powered by Disqus