renv (Reproducible Environment)
In R, the renv package is a tool for locking package versions on a per-project basis, enabling reproducible execution environments across different machines and team members. Use renv::init() to initialize a project, renv::snapshot() to record the current state in a lockfile, and renv::restore() to fully reproduce that state. It is particularly effective for preventing version-mismatch issues in team development and long-running projects.
Syntax
# -----------------------------------------------
# renv::init() — initialize the project with renv
# -----------------------------------------------
renv::init()
# Creates the renv/ directory and renv.lock in the project root
# Automatically detects existing install.packages() history and records it in the lockfile
# -----------------------------------------------
# renv::snapshot() — record the current environment in the lockfile
# -----------------------------------------------
renv::snapshot()
# Writes the versions of currently installed packages to renv.lock
# Use type="explicit" to limit the snapshot to packages listed in DESCRIPTION
renv::snapshot(type = "explicit") # records only packages listed in DESCRIPTION
# -----------------------------------------------
# renv::restore() — restore the environment to the lockfile state
# -----------------------------------------------
renv::restore()
# Installs and restores packages in bulk to match the versions recorded in renv.lock
# Run after a new team member clones the repository to synchronize their environment
# -----------------------------------------------
# renv::install() / renv::remove() — add or remove packages
# -----------------------------------------------
renv::install("dplyr") # installs the latest version
renv::install("dplyr@1.1.0") # installs a specific version
renv::install("tidyverse/dplyr") # installs from a GitHub repository
renv::remove("dplyr") # removes the package from the project environment
# -----------------------------------------------
# renv::status() — check for differences between environment and lockfile
# -----------------------------------------------
renv::status()
# Reports any discrepancies between the lockfile and the currently installed packages
# "The project is already synchronized." means everything matches
# -----------------------------------------------
# renv::update() — update packages to their latest versions
# -----------------------------------------------
renv::update() # updates all packages to their latest versions
renv::update("ggplot2") # updates only the specified package
Syntax / Function Reference
| Syntax / Function | Description |
|---|---|
renv::init() | Places the project under renv management, generating the renv/ directory and renv.lock. |
renv::snapshot() | Writes the version information of currently installed packages to renv.lock. |
renv::restore() | Reproduces the state recorded in renv.lock by installing or restoring packages in bulk. |
renv::install("pkg") | Installs the specified package into the project environment. Supports version pinning and GitHub installation. |
renv::remove("pkg") | Removes the specified package from the project environment. |
renv::update() | Updates installed packages to their latest versions. Pass a package name to update a single package. |
renv::status() | Reports differences between the lockfile and the current environment. Confirms whether they are in sync. |
renv::activate() | Activates an existing renv environment. Often called automatically via .Rprofile. |
renv::deactivate() | Disables renv management for the project and switches back to the global library. |
renv::dependencies() | Automatically detects and returns the list of packages that scripts in the project depend on. |
renv::clean() | Removes unnecessary packages from the project environment that are not recorded in the lockfile. |
Sample Code
renv_packrat.R
# renv_packrat.R — demo script for project environment management with renv
# Uses Yakuza series character data to demonstrate
# package installation, snapshots, and status checking
# -----------------------------------------------
# Load the renv package
# -----------------------------------------------
# If renv is not installed, run: install.packages("renv")
library(renv)
cat("=== renv version check ===\n")
cat(paste("renv version:", packageVersion("renv"), "\n\n"))
# -----------------------------------------------
# Check project state (assumes renv::init() has been run)
# -----------------------------------------------
# This script assumes it is running inside an renv-initialized project
# Run renv::init() first for a new project
cat("=== renv::status(): check sync state with the lockfile ===\n")
renv::status()
cat("\n")
# -----------------------------------------------
# Create character data (Yakuza series)
# -----------------------------------------------
# Data for 5 main characters from the Yakuza series
characters <- data.frame(
name = c("Kazuma Kiryu", "Goro Majima", "Haruka Sawamura", "Akira Nishikiyama", "Toshio Date"),
role = c("Protagonist", "Mad Dog", "Heroine", "Childhood friend", "Detective"),
heat_level = c(100L, 98L, 45L, 72L, 68L),
chapter = c(1L, 1L, 1L, 2L, 3L),
stringsAsFactors = FALSE
)
cat("=== Character data (data.frame) ===\n")
print(characters)
cat("\n")
# -----------------------------------------------
# Data operations with dplyr (assumes it is installed under renv)
# -----------------------------------------------
# The following requires dplyr to be installed
# Run renv::install("dplyr") before executing
if (requireNamespace("dplyr", quietly = TRUE)) {
library(dplyr)
cat("--- dplyr::filter(): filter characters with heat level >= 70 ---\n")
high_heat <- dplyr::filter(characters, heat_level >= 70)
print(high_heat)
cat("\n")
cat("--- dplyr::arrange(): sort by heat level descending ---\n")
sorted_chars <- dplyr::arrange(characters, desc(heat_level))
print(sorted_chars)
cat("\n")
cat("--- dplyr::mutate(): convert heat level to percentage string ---\n")
chars_pct <- dplyr::mutate(
characters,
heat_pct = paste0(heat_level, "%")
)
print(chars_pct[, c("name", "heat_level", "heat_pct")])
cat("\n")
} else {
cat("dplyr not found. Run renv::install(\"dplyr\") to install it.\n\n")
}
# -----------------------------------------------
# Detect script dependencies with renv::dependencies()
# -----------------------------------------------
cat("=== renv::dependencies(): check package dependencies for this script ===\n")
deps <- renv::dependencies(path = "renv_packrat.R", quiet = TRUE)
if (nrow(deps) > 0) {
cat("Detected dependencies:\n")
print(deps[, c("Package", "Version", "Source")])
} else {
cat("No dependencies detected.\n")
}
cat("\n")
# -----------------------------------------------
# Update the lockfile with renv::snapshot()
# -----------------------------------------------
cat("=== renv::snapshot(): update the lockfile ===\n")
cat("(Run this after installing new packages to update renv.lock)\n")
# Uncomment the following to actually take a snapshot
# renv::snapshot()
cat("Update renv.lock manually by calling renv::snapshot().\n\n")
# -----------------------------------------------
# Reproduction steps with renv::restore()
# -----------------------------------------------
cat("=== Steps to reproduce on another machine (renv::restore()) ===\n")
cat("1. Clone the repository with git clone\n")
cat("2. Start R (.Rprofile activates renv automatically)\n")
cat("3. Run renv::restore() to reproduce the environment as specified in renv.lock\n\n")
# -----------------------------------------------
# Character summary output
# -----------------------------------------------
cat("=== Yakuza character summary ===\n")
cat(sprintf("Total characters : %d\n", nrow(characters)))
cat(sprintf("Highest heat : %s (%d)\n",
characters$name[which.max(characters$heat_level)],
max(characters$heat_level)
))
cat(sprintf("Average heat : %.1f\n", mean(characters$heat_level)))
cat(sprintf("Earliest debut : %s (Chapter %d)\n",
paste(characters$name[characters$chapter == min(characters$chapter)], collapse = " / "),
min(characters$chapter)
))
Rscript renv_packrat.R
=== renv version check ===
renv version: 1.0.3
=== renv::status(): check sync state with the lockfile ===
The project is already synchronized with the lockfile.
=== Character data (data.frame) ===
name role heat_level chapter
1 Kazuma Kiryu Protagonist 100 1
2 Goro Majima Mad Dog 98 1
3 Haruka Sawamura Heroine 45 1
4 Akira Nishikiyama Childhood friend 72 2
5 Toshio Date Detective 68 3
--- dplyr::filter(): filter characters with heat level >= 70 ---
name role heat_level chapter
1 Kazuma Kiryu Protagonist 100 1
2 Goro Majima Mad Dog 98 1
3 Akira Nishikiyama Childhood friend 72 2
--- dplyr::arrange(): sort by heat level descending ---
name role heat_level chapter
1 Kazuma Kiryu Protagonist 100 1
2 Goro Majima Mad Dog 98 1
3 Akira Nishikiyama Childhood friend 72 2
4 Toshio Date Detective 68 3
5 Haruka Sawamura Heroine 45 1
--- dplyr::mutate(): convert heat level to percentage string ---
name heat_level heat_pct
1 Kazuma Kiryu 100 100%
2 Goro Majima 98 98%
3 Haruka Sawamura 45 45%
4 Akira Nishikiyama 72 72%
5 Toshio Date 68 68%
=== renv::dependencies(): check package dependencies for this script ===
Detected dependencies:
Package Version Source
1 renv NA <NA>
2 dplyr NA <NA>
=== renv::snapshot(): update the lockfile ===
(Run this after installing new packages to update renv.lock)
Update renv.lock manually by calling renv::snapshot().
=== Steps to reproduce on another machine (renv::restore()) ===
1. Clone the repository with git clone
2. Start R (.Rprofile activates renv automatically)
3. Run renv::restore() to reproduce the environment as specified in renv.lock
=== Yakuza character summary ===
Total characters : 5
Highest heat : Kazuma Kiryu (100)
Average heat : 76.6
Earliest debut : Kazuma Kiryu / Goro Majima / Haruka Sawamura (Chapter 1)
Common Mistakes
Mistake 1: renv::restore() fails with a dependency conflict
When multiple packages require different versions of the same dependency, renv::restore() may detect a conflict and throw an error. Check for discrepancies in advance with renv::status(), then either adjust the renv.lock contents manually or align the conflicting package versions.
renv_conflict.R
# Example of a conflict error when running renv::restore()
# renv.lock specifies dplyr 1.0.0, but another package requires dplyr >= 1.1.0
renv::restore()
# Error: package 'dplyr' [1.0.0] is not compatible with package 'xxx' which requires dplyr >= 1.1.0
# Check the conflict details
renv::status()
# Resolution: update the lockfile to the newer version
# renv::install("dplyr@1.1.0")
# renv::snapshot()
The following packages are out of sync:
Package Lockfile Library
dplyr 1.0.0 1.1.4
Use `renv::snapshot()` to update the lockfile.
Mistake 2: Package not found error in a Packrat environment
When migrating a project from Packrat (renv's predecessor) to renv, leaving the packrat/ directory in place can prevent renv from working correctly. Use renv::migrate() to migrate from Packrat to renv. After migration, verify that the environment is correctly recognized with renv::status().
renv_migrate.R
# Steps to migrate from Packrat to renv # 1. Initialize the project with renv renv::init() # 2. Migrate package information from Packrat renv::migrate() # 3. Verify the sync state renv::status() # 4. If everything looks good, update the snapshot # renv::snapshot()
* Migrating project from Packrat to renv ... * Initialized empty project. The project is already synchronized with the lockfile.
Overview
The renv package in R is an environment management tool that locks package versions on a per-project basis. Running renv::init() creates the renv/ directory and renv.lock in the project root, and subsequent package operations target the project-specific library path rather than the global library. Record the current state with renv::snapshot() and fully reproduce it in another environment with renv::restore(), making it highly effective for team development and ensuring reproducibility in research and analysis. Use renv::status() at any time to check for discrepancies between the lockfile and the current environment, and renv::dependencies() to automatically detect the packages a script requires. Install packages with renv::install(), which also supports version pinning ("dplyr@1.1.0") and GitHub installation ("tidyverse/dplyr"). For package installation, updating, and removal operations, see Package Installation and Management.
If you find any errors or copyright issues, please contact us.