renv demo

Maëlle Salmon

Goals for today

  • Why use renv?
  • How to use it?

🔗 https://maelle.github.io/renv-demo

Your project depends on

…its dependencies. To state the obvious 😅 Let’s concentrate on software dependencies.

… its dependencies, wherever they come from. CRAN, R-universe, GitHub.

… its dependencies as they are now. R packages evolve over time.

Future users of your code

including yourself 😉 should be able to easily use the same packages and their same versions to re-run your code.

Ever used sessionInfo() to list dependencies?

R version 4.2.0 (2022-04-22)
Platform: x86_64-pc-linux-gnu (64-bit)
Running under: Ubuntu 20.04.4 LTS

Matrix products: default
BLAS:   /usr/lib/x86_64-linux-gnu/blas/libblas.so.3.9.0
LAPACK: /usr/lib/x86_64-linux-gnu/lapack/liblapack.so.3.9.0

locale:
 [1] LC_CTYPE=en_US.utf8       LC_NUMERIC=C             
 [3] LC_TIME=en_US.utf8        LC_COLLATE=en_US.utf8    
 [5] LC_MONETARY=en_US.utf8    LC_MESSAGES=en_US.utf8   
 [7] LC_PAPER=en_US.utf8       LC_NAME=C                
 [9] LC_ADDRESS=C              LC_TELEPHONE=C           
[11] LC_MEASUREMENT=en_US.utf8 LC_IDENTIFICATION=C      

attached base packages:
[1] stats     graphics  grDevices utils     datasets  methods   base     

loaded via a namespace (and not attached):
 [1] compiler_4.2.0       magrittr_2.0.3       fastmap_1.1.0       
 [4] cli_3.4.1            tools_4.2.0          htmltools_0.5.3.9000
 [7] rstudioapi_0.14      yaml_2.3.5           stringi_1.7.8       
[10] rmarkdown_2.17       knitr_1.40           stringr_1.4.1       
[13] xfun_0.33            digest_0.6.29        jsonlite_1.8.2      
[16] rlang_1.0.6          evaluate_0.17       

This can’t be used directly.

Ever used sessionInfo() to list dependencies?

You were on the right track.

renv by Kevin Ushey is a better way to do that, with little overhead

First step: install renv!

Once per computer / per R update.

install.packages("renv")

The renv workflow in each project

  • Start with renv::init().

  • Install packages with renv::install("ggplot2").

  • Write code as usual.

  • Regularly, renv::snapshot() (renv::status()).

The renv workflow, when adopting a project

renv::restore()

Demo

  • The coolcool package has two versions on GitHub, with different functions.

  • My project1 uses the first version.

  • My project2 uses the second version.

In project1…

  • I can run coolcool::my_favorite_function().

  • I canNOT run coolcool::my_best_function().

In project2…

  • I canNOT run coolcool::my_favorite_function().

  • I can run coolcool::my_best_function().

Why is it so?

Anatomy of a project using renv

fs::dir_ls("../project1", all = TRUE)
../project1/.Rprofile      ../project1/.Rproj.user    
../project1/.git           ../project1/.gitignore     
../project1/R              ../project1/project1.Rproj 
../project1/renv           ../project1/renv.lock      
fs::dir_ls("../project1/renv", all = TRUE)
../project1/renv/.gitignore   ../project1/renv/activate.R   
../project1/renv/library      ../project1/renv/settings.dcf 
../project1/renv/staging      

The renv.lock file in project1

  "R": {
    "Version": "4.2.0",
    "Repositories": [
      {
        "Name": "RSPM",
        "URL": "https://packagemanager.rstudio.com/all/latest"
      },
      {
        "Name": "CRAN",
        "URL": "https://cloud.r-project.org"
      }
    ]
  },
  "Packages": {
    "coolcool": {
      "Package": "coolcool",
      "Version": "1.0.0",
      "Source": "GitHub",
      "RemoteType": "github",
      "RemoteHost": "api.github.com",
      "RemoteUsername": "maelle",
      "RemoteRepo": "coolcool",
      "RemoteRef": "v1.0.0",
      "RemoteSha": "f94dc7963719213b6cd1d4c4474b405c9d722a2b",
      "Hash": "51d05ff5c3d3ca1354bfa949a44d3c63",
      "Requirements": []
    },
    "renv": {
      "Package": "renv",
      "Version": "0.15.5",
      "Source": "Repository",
      "Repository": "RSPM",
      "Hash": "6a38294e7d12f5d8e656b08c5bd8ae34",
      "Requirements": []
    }
  }
}

The renv.lock file in project2

  "R": {
    "Version": "4.2.0",
    "Repositories": [
      {
        "Name": "RSPM",
        "URL": "https://packagemanager.rstudio.com/all/latest"
      },
      {
        "Name": "CRAN",
        "URL": "https://cloud.r-project.org"
      }
    ]
  },
  "Packages": {
    "coolcool": {
      "Package": "coolcool",
      "Version": "2.0.0",
      "Source": "GitHub",
      "RemoteType": "github",
      "RemoteHost": "api.github.com",
      "RemoteUsername": "maelle",
      "RemoteRepo": "coolcool",
      "RemoteRef": "v2.0.0",
      "RemoteSha": "0b896d6c30dfb2b0ace3a881642769851aaf100c",
      "Hash": "8da8b82994ba0ecdc7d2c6cee0cd8b76",
      "Requirements": []
    },
    "renv": {
      "Package": "renv",
      "Version": "0.15.5",
      "Source": "Repository",
      "Repository": "RSPM",
      "Hash": "6a38294e7d12f5d8e656b08c5bd8ae34",
      "Requirements": []
    }
  }
}

The difference

"Version": "1.0.0"

vs

"Version": "2.0.0"

How do we get there?

project0

  • usethis::create_project("../project0")

  • renv::init() then 👀 look 👀

  • renv::install("maelle/coolcool")

  • Create r/blop.R, write coolcool::my_best_function()

  • renv::status()

  • renv::snapshot() then 👀 look 👀

  • renv::install("usethis"); usethis::use_git(); usethis::use_github()

project0 from GitHub

  • Close project. In another folder create_from_github("maelle/project0")

  • 👀 look 👀

  • coolcool::my_best_function() 😭

  • renv::restore()

  • 👀 look 👀

  • coolcool::my_best_function() 😁

Zoom on renv::install()

Will it take ages to re-install packages in each project? 😱

No! renv creates a central cache from which it can pick packages quickly.

The first installation might take time, the second no because it uses the cache.

What if I like sessionInfo()?

Finding R package dependencies ... Done!
                                                     Source   Package Require
1        /home/maelle/Documents/EMODnet/renv-demo/index.qmd      glue        
2        /home/maelle/Documents/EMODnet/renv-demo/index.qmd      httr        
3        /home/maelle/Documents/EMODnet/renv-demo/index.qmd        fs        
4        /home/maelle/Documents/EMODnet/renv-demo/index.qmd      brio        
5        /home/maelle/Documents/EMODnet/renv-demo/index.qmd      glue        
6        /home/maelle/Documents/EMODnet/renv-demo/index.qmd      brio        
7        /home/maelle/Documents/EMODnet/renv-demo/index.qmd      glue        
8        /home/maelle/Documents/EMODnet/renv-demo/index.qmd      renv        
9        /home/maelle/Documents/EMODnet/renv-demo/index.qmd rmarkdown        
10 /home/maelle/Documents/EMODnet/renv-demo/index.rmarkdown rmarkdown        
11 /home/maelle/Documents/EMODnet/renv-demo/index.rmarkdown      glue        
12 /home/maelle/Documents/EMODnet/renv-demo/index.rmarkdown      httr        
13 /home/maelle/Documents/EMODnet/renv-demo/index.rmarkdown        fs        
14 /home/maelle/Documents/EMODnet/renv-demo/index.rmarkdown      brio        
15 /home/maelle/Documents/EMODnet/renv-demo/index.rmarkdown      glue        
16 /home/maelle/Documents/EMODnet/renv-demo/index.rmarkdown      brio        
17 /home/maelle/Documents/EMODnet/renv-demo/index.rmarkdown      glue        
18 /home/maelle/Documents/EMODnet/renv-demo/index.rmarkdown      renv        
   Version   Dev
1          FALSE
2          FALSE
3          FALSE
4          FALSE
5          FALSE
6          FALSE
7          FALSE
8          FALSE
9          FALSE
10         FALSE
11         FALSE
12         FALSE
13         FALSE
14         FALSE
15         FALSE
16         FALSE
17         FALSE
18         FALSE

RStudio IDE or not

renv works without RStudio IDE too!

It is well supported in RStudio IDE, for instance when creating a new project from the menu.

Summary

Once per computer: install.packages("renv").

In each project:

  • renv::init() once,
  • renv::install() as often as needed,
  • renv::snapshot() regularly.

When adopting a project: renv::restore().

🔗 https://maelle.github.io/renv-demo

Further resources on renv itself

Further, further resources