Skip to contents

Renv creates renv.lock file which is a JSON object and that can be a bit unweildy to handle. What if you want to find out how many packages you have? Or how many packages from installed from CRAN. What if you want to remove a package from the list? What if you want to compare lockfiles? And why not do it all from the comfort of R and tidy tools.

1 Read lockfile

Load the library and let’s read in a lock file. If paths are named, they are used in downstream functions else they are named automatically.

library(renvtools)
# using a sample lockfile from the package
path <- file.path(system.file("extdata", package = "renvtools"), "renv-r4.4.1.lock")
# provide path to a lock file, set format to tibble
lst <- read_lock(path)
lst
R version: 4.4.1
Bioc version: 3.19
renv version: 1.0.7
Packages: 294

You can get some useful information about the lockfile. You can also explore this data as you would explore a list.

[1] "4.4.1"
[1] "3.19"
[1] "1.0.7"
[1] "1.1.4"

The default is to read into a list. Change format to tibble to read as table.

tbl <- read_lock(path, format = "tibble")
tbl
R version: 4.4.1
Bioc version: 3.19
# A tibble: 294 x 14
   Package     Version  Source  Repository Hash  Requirements OS_type RemoteType
   <chr>       <chr>    <chr>   <chr>      <chr> <list>       <chr>   <chr>
 1 BH          1.84.0-0 Reposi~ RSPM       a823~ <NULL>       <NA>    <NA>
 2 BiocManager 1.30.23  Reposi~ RSPM       47e9~ <chr [1]>    <NA>    <NA>
 3 BiocVersion 3.19.1   Biocon~ Bioconduc~ b892~ <chr [1]>    <NA>    <NA>
 4 CFtime      1.4.0    Reposi~ RSPM       630f~ <chr [2]>    <NA>    <NA>
 5 DBI         1.2.3    Reposi~ RSPM       065a~ <chr [2]>    <NA>    <NA>
 6 DiagrammeR  1.0.11   Reposi~ RSPM       584c~ <chr [19]>   <NA>    <NA>
 7 FNN         1.1.4    Reposi~ RSPM       eaab~ <chr [1]>    <NA>    <NA>
 8 KernSmooth  2.23-24  Reposi~ CRAN       9f33~ <chr [2]>    <NA>    <NA>
 9 Lahman      11.0-0   Reposi~ RSPM       5b6f~ <chr [2]>    <NA>    <NA>
10 LearnBayes  2.15.1   Reposi~ RSPM       b2dd~ <NULL>       <NA>    <NA>
# i 284 more rows
# i 6 more variables: RemoteHost <chr>, RemoteRepo <chr>, RemoteUsername <chr>,
#   RemotePkgRef <chr>, RemoteRef <chr>, RemoteSha <chr>

  Note that the list and tibble formats may not be identical in information depending on the input especially in case of NAs and NULLs.

This gives you a tibble with all the package information. Now you can handle this like you would with any tibble.

suppressMessages(library(dplyr))
suppressMessages(library(tidyr))

# number of packages by source
tbl |>
  group_by(Source) |>
  count()
# A tibble: 4 x 2
# Groups:   Source [4]
  Source           n
  <chr>        <int>
1 Bioconductor     4
2 GitHub           1
3 Repository     288
4 unknown          1
# number of packages by repository
tbl |>
  group_by(Repository) |>
  count()
# A tibble: 4 x 2
# Groups:   Repository [4]
  Repository            n
  <chr>             <int>
1 Bioconductor 3.19     4
2 CRAN                 16
3 RSPM                272
4 <NA>                  2
# number of packages by source and repository
tbl |>
  group_by(Source, Repository) |>
  count() |>
  pivot_wider(names_from = Repository, values_from = n)
# A tibble: 4 x 5
# Groups:   Source [4]
  Source       `Bioconductor 3.19`  `NA`  CRAN  RSPM
  <chr>                      <int> <int> <int> <int>
1 Bioconductor                   4    NA    NA    NA
2 GitHub                        NA     1    NA    NA
3 Repository                    NA    NA    16   272
4 unknown                       NA     1    NA    NA
# number of dependency packages for each package
tbl |>
  group_by(Package) |>
  summarize(N = length(unlist(Requirements)))
# A tibble: 294 x 2
   Package         N
   <chr>       <int>
 1 BH              0
 2 BiocManager     1
 3 BiocVersion     1
 4 CFtime          2
 5 DBI             2
 6 DiagrammeR     19
 7 FNN             1
 8 KernSmooth      2
 9 Lahman          2
10 LearnBayes      0
# i 284 more rows

Read several lock files and you get a list of tibbles or a list of lists.

paths <- list.files(file.path(system.file("extdata", package = "renvtools")), full.names = TRUE)
# read as list
# read_lock(paths[1:3], format = "list")
# read as tibble
read_lock(paths[1:3], format = "tibble")
$lf_1
R version: 3.5.3
# A tibble: 197 x 10
   Package  Version Source Hash  RemoteType RemoteHost RemoteRepo RemoteUsername
   <chr>    <chr>   <chr>  <chr> <chr>      <chr>      <chr>      <chr>
 1 ape      5.3     CRAN   c94d~ <NA>       <NA>       <NA>       <NA>
 2 askpass  1.1     CRAN   ff8e~ <NA>       <NA>       <NA>       <NA>
 3 assertt~ 0.2.1   CRAN   263e~ <NA>       <NA>       <NA>       <NA>
 4 backpor~ 1.1.3   CRAN   d5d2~ <NA>       <NA>       <NA>       <NA>
 5 base64e~ 0.1-3   CRAN   eec0~ <NA>       <NA>       <NA>       <NA>
 6 BH       1.69.0~ CRAN   88e6~ <NA>       <NA>       <NA>       <NA>
 7 bibtex   0.4.2   CRAN   be04~ <NA>       <NA>       <NA>       <NA>
 8 bitops   1.0-6   CRAN   f72d~ <NA>       <NA>       <NA>       <NA>
 9 broom    0.5.1   CRAN   3bca~ <NA>       <NA>       <NA>       <NA>
10 callr    3.2.0   CRAN   7af0~ <NA>       <NA>       <NA>       <NA>
# i 187 more rows
# i 2 more variables: RemoteRef <chr>, RemoteSha <chr>

$lf_2
R version: 3.6.1
# A tibble: 168 x 5
   Package      Version  Source     Repository Hash
   <chr>        <chr>    <chr>      <chr>      <chr>
 1 BH           1.72.0-3 Repository CRAN       8f9ce74c6417d61f0782cbae5fd2b7b0
 2 DBI          1.1.0    Repository CRAN       4744be45519d675af66c28478720fce5
 3 DT           0.12     Repository CRAN       0e120603cc57e4f1d741f739aa8147ba
 4 Formula      1.2-3    Repository CRAN       0537b6f1f38ea1fd514089192724bb6e
 5 Hmisc        4.3-1    Repository CRAN       b354bb2e63e1d6947eb05fa3bc355b2f
 6 MASS         7.3-51.5 Repository CRAN       9efe80472b21189ebab1b74169808c26
 7 Matrix       1.2-18   Repository CRAN       08588806cba69f04797dab50627428ed
 8 MatrixModels 0.4-1    Repository CRAN       d57ac35220b39c591388ab3a080f9cbe
 9 R6           2.4.1    Repository CRAN       292b54f8f4b94669b08f94e5acce6be2
10 RColorBrewer 1.1-2    Repository CRAN       e031418365a7f7a766181ab5a41a5716
# i 158 more rows

$lf_3
R version: 4.0.5
# A tibble: 424 x 6
   Package       Version  Source     Repository Hash                Requirements
   <chr>         <chr>    <chr>      <chr>      <chr>               <list>
 1 BH            1.72.0-3 Repository CRAN       8f9ce74c6417d61f07~ <NULL>
 2 BayesianTools 0.1.8    Repository CRAN       6f37f391a9029a6490~ <chr [14]>
 3 Brobdingnag   1.2-6    Repository CRAN       365629a3ac7243df8e~ <NULL>
 4 DBI           1.1.0    Repository CRAN       4744be45519d675af6~ <NULL>
 5 DHARMa        0.4.6    Repository CRAN       ffebef4763cbacec39~ <chr [6]>
 6 DT            0.15     Repository CRAN       85738c69035e67ec4b~ <chr [6]>
 7 Epi           2.46     Repository CRAN       8c034ee3794ad710b8~ <chr [12]>
 8 FNN           1.1.3    Repository CRAN       b56998fff55e4a4b48~ <NULL>
 9 Formula       1.2-3    Repository CRAN       0537b6f1f38ea1fd51~ <NULL>
10 GGally        2.0.0    Repository CRAN       f767c7f049252543d1~ <chr [9]>
# i 414 more rows

2 Write lockfile

Filter packages as needed and then write to a new lock file.

  Reading a loackfile and then writing it may not give identical lockfiles as NAs and NULLs may be discarded.

# exclude bioconductor packages
tbl1 <- tbl |> filter(Source != "Bioconductor")
write_lock(tbl1, "renv-mod.lock")

3 Summarizing lock files

Summarize multiple lock files.

paths <- list.files(system.file("extdata", package = "renvtools"), full.names = TRUE)
l <- read_lock(paths, format = "list")
d <- summarize_lock(l)
d
# A tibble: 8 x 8
  label rver  renvver pkgs_len repositories sources      pkgs       pkgs_req
  <chr> <chr> <chr>      <int> <named list> <named list> <named li> <named list>
1 lf_1  3.5.3 0.9.2        197 <df [1 x 2]> <df [2 x 2]> <chr>      <named list>
2 lf_2  3.6.1 0.11.0       168 <df [1 x 2]> <df [1 x 2]> <chr>      <named list>
3 lf_3  4.0.5 0.16.0       424 <df [1 x 2]> <df [1 x 2]> <chr>      <named list>
4 lf_4  4.1.2 1.0.3        391 <df [3 x 2]> <df [1 x 2]> <chr>      <named list>
5 lf_5  4.2.2 1.0.4        256 <df [1 x 2]> <df [3 x 2]> <chr>      <named list>
6 lf_6  4.3.2 1.0.3        668 <df [3 x 2]> <df [3 x 2]> <chr>      <named list>
7 lf_7  4.4.1 1.0.7        294 <df [3 x 2]> <df [4 x 2]> <chr>      <named list>
8 lf_8  <NA>  <NA>          16 <df [2 x 2]> <df [1 x 2]> <chr [16]> <named list>

For example, visualize the difference in number of packages between lockfiles. Note that this step requires additional package.

library(UpSetR)
lst <- d$pkgs
names(lst) <- basename(paths)
upset(fromList(lst), order.by = "freq")

4 Comparing lockfiles

Compare two or more lockfiles in a pairwise manner.

paths <- list.files(system.file("extdata", package = "renvtools"), full.names = TRUE)
l <- read_lock(paths, format = "list")
compare_lock(l)
# A tibble: 28 x 18
   a     b     a_rver b_rver a_renvver b_renvver jaccard a_pkgs_len b_pkgs_len
   <chr> <chr> <chr>  <chr>  <chr>     <chr>       <dbl>      <int>      <int>
 1 lf_1  lf_2  3.5.3  3.6.1  0.9.2     0.11.0     0.448         197        168
 2 lf_1  lf_3  3.5.3  4.0.5  0.9.2     0.16.0     0.316         197        424
 3 lf_1  lf_4  3.5.3  4.1.2  0.9.2     1.0.3      0.292         197        391
 4 lf_1  lf_5  3.5.3  4.2.2  0.9.2     1.0.4      0.373         197        256
 5 lf_1  lf_6  3.5.3  4.3.2  0.9.2     1.0.3      0.257         197        668
 6 lf_1  lf_7  3.5.3  4.4.1  0.9.2     1.0.7      0.292         197        294
 7 lf_1  lf_8  3.5.3  <NA>   0.9.2     <NA>       0.0340        197         16
 8 lf_2  lf_3  3.6.1  4.0.5  0.11.0    0.16.0     0.349         168        424
 9 lf_2  lf_4  3.6.1  4.1.2  0.11.0    1.0.3      0.354         168        391
10 lf_2  lf_5  3.6.1  4.2.2  0.11.0    1.0.4      0.457         168        256
# i 18 more rows
# i 9 more variables: a_pkgs_len_unique <int>, b_pkgs_len_unique <int>,
#   pkgs_total_len <int>, a_pkgs <list>, b_pkgs <list>, a_pkgs_unique <list>,
#   b_pkgs_unique <list>, pkgs_common <list>, pkgs_total <list>
      a    b a_rver b_rver a_renvver b_renvver    jaccard a_pkgs_len b_pkgs_len
1  lf_1 lf_2  3.5.3  3.6.1     0.9.2    0.11.0 0.44841270        197        168
2  lf_1 lf_3  3.5.3  4.0.5     0.9.2    0.16.0 0.31567797        197        424
3  lf_1 lf_4  3.5.3  4.1.2     0.9.2     1.0.3 0.29230769        197        391
4  lf_1 lf_5  3.5.3  4.2.2     0.9.2     1.0.4 0.37272727        197        256
5  lf_1 lf_6  3.5.3  4.3.2     0.9.2     1.0.3 0.25726744        197        668
6  lf_1 lf_7  3.5.3  4.4.1     0.9.2     1.0.7 0.29210526        197        294
7  lf_1 lf_8  3.5.3   <NA>     0.9.2      <NA> 0.03398058        197         16
8  lf_2 lf_3  3.6.1  4.0.5    0.11.0    0.16.0 0.34851936        168        424
9  lf_2 lf_4  3.6.1  4.1.2    0.11.0     1.0.3 0.35351090        168        391
10 lf_2 lf_5  3.6.1  4.2.2    0.11.0     1.0.4 0.45704467        168        256
11 lf_2 lf_6  3.6.1  4.3.2    0.11.0     1.0.3 0.22760646        168        668
12 lf_2 lf_7  3.6.1  4.4.1    0.11.0     1.0.7 0.35882353        168        294
13 lf_2 lf_8  3.6.1   <NA>    0.11.0      <NA> 0.03954802        168         16
14 lf_3 lf_4  4.0.5  4.1.2    0.16.0     1.0.3 0.36744966        424        391
15 lf_3 lf_5  4.0.5  4.2.2    0.16.0     1.0.4 0.36000000        424        256
16 lf_3 lf_6  4.0.5  4.3.2    0.16.0     1.0.3 0.31724970        424        668
17 lf_3 lf_7  4.0.5  4.4.1    0.16.0     1.0.7 0.28214286        424        294
18 lf_3 lf_8  4.0.5   <NA>    0.16.0      <NA> 0.02088167        424         16
19 lf_4 lf_5  4.1.2  4.2.2     1.0.3     1.0.4 0.38247863        391        256
20 lf_4 lf_6  4.1.2  4.3.2     1.0.3     1.0.3 0.32540676        391        668
21 lf_4 lf_7  4.1.2  4.4.1     1.0.3     1.0.7 0.41528926        391        294
22 lf_4 lf_8  4.1.2   <NA>     1.0.3      <NA> 0.03037975        391         16
23 lf_5 lf_6  4.2.2  4.3.2     1.0.4     1.0.3 0.32758621        256        668
24 lf_5 lf_7  4.2.2  4.4.1     1.0.4     1.0.7 0.39949109        256        294
25 lf_5 lf_8  4.2.2   <NA>     1.0.4      <NA> 0.03422053        256         16
26 lf_6 lf_7  4.3.2  4.4.1     1.0.3     1.0.7 0.43154762        668        294
27 lf_6 lf_8  4.3.2   <NA>     1.0.3      <NA> 0.02395210        668         16
28 lf_7 lf_8  4.4.1   <NA>     1.0.7      <NA> 0.05442177        294         16
   a_pkgs_len_unique b_pkgs_len_unique pkgs_total_len
1                 84                55            252
2                 48               275            472
3                 64               258            455
4                 74               133            330
5                 20               491            688
6                 86               183            380
7                190                 9            206
8                 15               271            439
9                 22               245            413
10                35               123            291
11                13               513            681
12                46               172            340
13               161                 9            177
14               205               172            596
15               244                76            500
16               161               405            829
17               266               136            560
18               415                 7            431
19               212                77            468
20               131               408            799
21               190                93            484
22               379                 4            395
23                28               440            696
24                99               137            393
25               247                 7            263
26               378                 4            672
27               652                 0            668
28               278                 0            294

5 Other details

The lists are a class of it’s own called rt_list. This is why they are printed a bit differently. But, they can be treated like regular lists.

path <- file.path(system.file("extdata", package = "renvtools"), "renv-r4.4.1.lock")
lst <- read_lock(path, format = "list")
lst
R version: 4.4.1
Bioc version: 3.19
renv version: 1.0.7
Packages: 294
class(lst)
[1] "rt_list" "list"   

The tibbles are also a class of it’s own called rt_tibble.

path <- file.path(system.file("extdata", package = "renvtools"), "renv-r4.4.1.lock")
tbl <- read_lock(path, format = "tibble")
tbl
R version: 4.4.1
Bioc version: 3.19
# A tibble: 294 x 14
   Package     Version  Source  Repository Hash  Requirements OS_type RemoteType
   <chr>       <chr>    <chr>   <chr>      <chr> <list>       <chr>   <chr>
 1 BH          1.84.0-0 Reposi~ RSPM       a823~ <NULL>       <NA>    <NA>
 2 BiocManager 1.30.23  Reposi~ RSPM       47e9~ <chr [1]>    <NA>    <NA>
 3 BiocVersion 3.19.1   Biocon~ Bioconduc~ b892~ <chr [1]>    <NA>    <NA>
 4 CFtime      1.4.0    Reposi~ RSPM       630f~ <chr [2]>    <NA>    <NA>
 5 DBI         1.2.3    Reposi~ RSPM       065a~ <chr [2]>    <NA>    <NA>
 6 DiagrammeR  1.0.11   Reposi~ RSPM       584c~ <chr [19]>   <NA>    <NA>
 7 FNN         1.1.4    Reposi~ RSPM       eaab~ <chr [1]>    <NA>    <NA>
 8 KernSmooth  2.23-24  Reposi~ CRAN       9f33~ <chr [2]>    <NA>    <NA>
 9 Lahman      11.0-0   Reposi~ RSPM       5b6f~ <chr [2]>    <NA>    <NA>
10 LearnBayes  2.15.1   Reposi~ RSPM       b2dd~ <NULL>       <NA>    <NA>
# i 284 more rows
# i 6 more variables: RemoteHost <chr>, RemoteRepo <chr>, RemoteUsername <chr>,
#   RemotePkgRef <chr>, RemoteRef <chr>, RemoteSha <chr>
class(tbl)
[1] "rt_tibble"  "tbl_df"     "tbl"        "data.frame"

The rt_tibble objects contains only information about the packages. What about other metadata such as R version, Bioconductor version etc? These are stored as attributes along with the tibble. They are used when writing lock files. They can be accessed using attr().

attr(tbl, "metadata")
$R
$R$Version
[1] "4.4.1"

$R$Repositories
  Name                         URL
1 CRAN https://p3m.dev/cran/latest


$Bioconductor
$Bioconductor$Version
[1] "3.19"

Or from a list of renvtools tibbles.

paths <- list.files(file.path(system.file("extdata", package = "renvtools")), full.names = TRUE)
tbl <- read_lock(paths, format = "tibble")
lapply(tbl, attr, "metadata")
$lf_1
$lf_1$renv
$lf_1$renv$Version
[1] "0.9.2"


$lf_1$R
$lf_1$R$Version
[1] "3.5.3"

$lf_1$R$Repositories
  Name                       URL
1   NA https://cran.rstudio.com/



$lf_2
$lf_2$R
$lf_2$R$Version
[1] "3.6.1"

$lf_2$R$Repositories
  Name                      URL
1 CRAN https://cran.rstudio.com



$lf_3
$lf_3$R
$lf_3$R$Version
[1] "4.0.5"

$lf_3$R$Repositories
  Name                         URL
1 CRAN https://cloud.r-project.org



$lf_4
$lf_4$R
$lf_4$R$Version
[1] "4.1.2"

$lf_4$R$Repositories
  Name                                   URL
1 CRAN              https://cran.rstudio.com
2  pik https://rse.pik-potsdam.de/r/packages



$lf_5
$lf_5$R
$lf_5$R$Version
[1] "4.2.2"

$lf_5$R$Repositories
           Name                                                    URL
1      BioCsoft            https://bioconductor.org/packages/3.16/bioc
2       BioCann https://bioconductor.org/packages/3.16/data/annotation
3       BioCexp https://bioconductor.org/packages/3.16/data/experiment
4 BioCworkflows       https://bioconductor.org/packages/3.16/workflows
5     BioCbooks           https://bioconductor.org/packages/3.16/books
6          CRAN                               https://cran.rstudio.com


$lf_5$Bioconductor
$lf_5$Bioconductor$Version
[1] "3.16"



$lf_6
$lf_6$R
$lf_6$R$Version
[1] "4.3.2"

$lf_6$R$Repositories
  Name                         URL
1 CRAN https://p3m.dev/cran/latest


$lf_6$Bioconductor
$lf_6$Bioconductor$Version
[1] "3.18"



$lf_7
$lf_7$R
$lf_7$R$Version
[1] "4.4.1"

$lf_7$R$Repositories
  Name                         URL
1 CRAN https://p3m.dev/cran/latest


$lf_7$Bioconductor
$lf_7$Bioconductor$Version
[1] "3.19"



$lf_8
named list()

6 Session

R version 4.4.1 (2024-06-14)
Platform: aarch64-apple-darwin20.0.0
Running under: macOS 15.1

Matrix products: default
BLAS/LAPACK: /opt/homebrew/Caskroom/miniforge/base/envs/r-4.4-arm/lib/libopenblas.0.dylib;  LAPACK version 3.12.0

locale:
[1] C

time zone: Europe/Stockholm
tzcode source: system (macOS)

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

other attached packages:
[1] UpSetR_1.4.0         tidyr_1.3.1          dplyr_1.1.4
[4] renvtools_0.0.0.9001

loaded via a namespace (and not attached):
 [1] gtable_0.3.5      jsonlite_1.8.8    compiler_4.4.1    renv_1.0.7
 [5] tidyselect_1.2.1  Rcpp_1.0.13       gridExtra_2.3     scales_1.3.0
 [9] yaml_2.3.10       fastmap_1.2.0     ggplot2_3.5.1     R6_2.5.1
[13] plyr_1.8.9        labeling_0.4.3    generics_0.1.3    knitr_1.48
[17] tibble_3.2.1      munsell_0.5.1     pillar_1.9.0      rlang_1.1.4
[21] utf8_1.2.4        xfun_0.48         cli_3.6.3         withr_3.0.1
[25] magrittr_2.0.3    digest_0.6.37     grid_4.4.1        rstudioapi_0.16.0
[29] lifecycle_1.0.4   vctrs_0.6.5       evaluate_0.24.0   glue_1.8.0
[33] farver_2.1.2      fansi_1.0.6       colorspace_2.1-1  rmarkdown_2.28
[37] purrr_1.0.2       tools_4.4.1       pkgconfig_2.0.3   htmltools_0.5.8.1