Dependency management

🔗 Reproducibility guidelines:

  • Heather et al. 2025: List dependencies and versions.
  • NHS Levels of RAP (🥈): Repository includes dependency information.

Dependency management is about keeping track of the environment used for your project. This includes the version of your programming languages, any packages used, and their versions.

It acts like a time capsule, allowing you to return to a project later and run it with the exact same packages and versions, reproducing the results generated previously.

Dependency management enables you to isolate environments for different projects. Each project can have it’s own set of dependencies, preventing conflicts and making it easy to switch between projects.

It is also important for collaboration, so that everyone working on the project is using the same environment.


1 Tools for dependency management

There are several popular tools for managing Python dependencies in isolated environment. Below, we compare some of main options, and consider some of the main factors that may influence your choice:

  • Python version management: Can the tool install and switch between different Python versions? This is crucial for projects that require specific versions.
  • Default environment location: Does the tool create environments in the project folder or in a central location? Central locations can be reused across multiple repositories from a single project, while repository-specific environments keep everything together.
  • Speed: How fast does the tool create environments and install packages?
  • Build and publish packages: If you are structuring your research as a package, you may wish to use one tool - or separate tools - for dependency management and creation of your package.

Other details like the package source (where packages come from) and config files (which files list dependencies) are also included.


venv was introduced with Python 3.3, and quickly replaced pyvenv and virtualenv as the standard way of managing virtual environments. It is included as part of the standard Python library, and so requires no installation.

Feature venv
Manages different python versions No (uses the Python version it was invoked with)
Default env location Project directory (e.g. ./venv)
Customise location? Yes
Default package source PyPI
Config file requirements.txt
Speed Fast
Build and publish packages? No


conda comes with Anaconda and Miniconda or can be installed separately. It can install and manage multiple Python versions, and non-Python dependencies (e.g. R, Node.js, compilers and system libraries). mamba (2020) is a drop-in replacement for conda written in C++ which offers faster installs and clearer conflict messages.

Feature conda
Manages different python versions? Yes (downloads and manages python versions)
Default env location Central location (e.g. ~/.conda/envs/)
Customise location? Yes
Default package source conda channels or PyPI
Config file environment.yaml or environment.yml
Speed Slow (conda) or fast (mamba)
Build and publish packages? No


poetry was focused on simplifying dependency management and packaging. It uses a pyproject.toml file to manage dependencies and create environments, and to build packages. It can use a specific Python version if installed on your system, but does not install Python itself.

Feature poetry
Manages different python versions? No (relies on system-installed Python, but can select among installed versions)
Default env location Central cache (e.g. ~/.cache/pypoetry/virtualenvs/)
Customise location? Yes
Default package source PyPI
Config file pyproject.toml and poetry.lock
Speed Fast
Build and publish packages? Yes


uv is a modern tool developed by the creators of Ruff and written in Rust. It is designed to be very fast - 10-100x faster than pip or conda. It combines features of pip, venv and poetry, and can be used to build and publish packages.

Feature uv
Manages different python versions? Yes (downloads and manages python versions)
Default env location Project directory (e.g. ./.venv)
Customise location? No
Default package source PyPI
Config file pyproject.toml and uv.lock
Speed Very fast
Build and publish packages? Yes

In R, the most popular tool for managing dependencies in R is renv. This replaced and improved upon the previous tool, Packrat.

However, renv does not manage the R version used, so we also mention manual installation of R versions (in Section 3), rig (manages R version but not packages) and rv (a new tool that manages both).

Note: Switching between R versions is less common and more complicated than in many other languages, mainly as it is not always straightforward to install different versions, and as it may then be tricky to install compatible packages for each version of R, if no longer available on CRAN.


renv is currently the standard way for managing R package environments. It is distributed as an R package.

Feature renv
Package manager? Yes
Manages different R versions? No (uses the R version it was invoked with)
Default env location Project directory (e.g. ./renv)
Customise location? Yes
Config file renv.lock


rig is a tool for managing multiple R versions on a system - but it is not a package environment manager.

Feature rig
Package manager? No
Manages different R versions? Yes (installs and switches between R versions)
Default env location Central location
Customise location? Yes
Config file N/A


rv (TBC - in development)
https://github.com/A2-ai/rv

rv is a package manager currently in development which aims to provide a more modern, declarative workflow. You can declare an R version up-front and, whilst it will not automate installation or switching of R versions, it will warn/error if you try to use a different version. Also, it requires all dependencies to be specified before installation, rather than taking snapshots as you go along like with renv. These dependencies are saved in an rproject.toml file.

Feature rig
Package manager? Yes
Manages different R versions? Partially (relies on system-installed R, but can select among installed versions, and will warn/error if the running R version does not match the declared version)
Default env location Project directory (e.g. ./rv)
Customise location? Yes
Config file rproject.toml plus a generated lockfile


2 Step-by-step instructions

In this book and in our examples we have used conda - a popular, established tools that allows you to specify the Python version. This section walks you through setting up a conda environment - with the steps for other package managers overviewed in Section 3.

Mamba

Mamba is a drop-in replacement for conda that is often preferred as it is:

  • Faster than conda.
  • Better at dealing with dependency conflicts, providing more helpful messages in cases where environments fail to builds due to clashing requirements of different packages.

To use mamba, simply replace conda in all the commands below with mamba.

In our repositories for this book, we have used renv.


2.1 Installing the environment manager

Refer to the conda or mamba documentation for the latest instructions on installing conda/mamba for your operating system (windows, mac or linux).

Before getting started, you’ll need to install renv.

install.packages("renv")


2.2 Creating the environment

Create an environment file. In the project root, we create environment.yaml.

touch environment.yaml

Within this file, we add three sections:

  • Name. The environment name.
  • Channels. Where to find packages (e.g. conda-forge).
  • Dependencies. The packages you need.

When first creating our environment, we just list the dependencies we know we need at this point - we can always add more later! At the start of a project, you might only know one: python.

As an example, we will add simpy and python.

name: des-example
channels:
  - conda-forge
dependencies:
  - python
  - simpy
Conda channels

Channels are locations where conda stores and retrieves packages. You can choose which channel to use, and can a select a few with an order of priority.

We have used conda-forge which is a community-maintained channel run by volunteers. It offers a wide range of packages and is a popular choice for many users.

Other main channels include:

  • default and anaconda - Maintained by Anaconda’s engineers and designed for high security and stability. Organisations with 200 or more employees have to pay to use this channel (excluding students and non-commercial research at universities)
  • bioconda - Volunteer-run, offers bioinformatics-related packages.


Build and activate the environment. In the command line, run the following to create your environment:

conda env create --file environment.yaml

You can then activate it (replacing des-example with your environment name):

conda activate des-example

To confirm your environment contains the expected packages, run:

conda list

This will output a list of packages, versions, builds and channels. For example, it may look similar to:

(des-example) amy@xps:~/Documents/hospital-des$ conda list
# packages in environment at /home/amy/mambaforge/envs/des-example:
#
# Name                    Version                   Build  Channel
_libgcc_mutex             0.1                 conda_forge    conda-forge
_openmp_mutex             4.5                       2_gnu    conda-forge
bzip2                     1.0.8                h4bc722e_7    conda-forge
ca-certificates           2025.1.31            hbd8a1cb_1    conda-forge
ld_impl_linux-64          2.43                 h712a8e2_4    conda-forge
libexpat                  2.7.0                h5888daf_0    conda-forge
libffi                    3.4.6                h2dba641_1    conda-forge
libgcc                    14.2.0               h767d61c_2    conda-forge
libgcc-ng                 14.2.0               h69a702a_2    conda-forge
libgomp                   14.2.0               h767d61c_2    conda-forge
liblzma                   5.8.1                hb9d3cd8_0    conda-forge
libmpdec                  4.0.0                h4bc722e_0    conda-forge
libsqlite                 3.49.1               hee588c1_2    conda-forge
libuuid                   2.38.1               h0b41bf4_0    conda-forge
libzlib                   1.3.1                hb9d3cd8_2    conda-forge
ncurses                   6.5                  h2d0b736_3    conda-forge
openssl                   3.5.0                h7b32b05_0    conda-forge
pip                       25.0.1             pyh145f28c_0    conda-forge
python                    3.13.3          hf636f53_101_cp313    conda-forge
python_abi                3.13                    7_cp313    conda-forge
readline                  8.2                  h8c095d6_2    conda-forge
simpy                     4.1.1              pyhd8ed1ab_1    conda-forge
tk                        8.6.13          noxft_h4845f30_101    conda-forge
tzdata                    2025b                h78e105d_0    conda-forge

Create an R project. It’s best to use renv within an R project. In RStudio, select File > New Project…, and choose Existing Directory.

Navigate to your project directory, then select Create Project.

This creates:

  • .Rproj: project file (contains some settings for the project).
  • .Rproj.user: hidden folder with temporary project files (e.g. auto-saved source documents).

Note: R projects are commonly created and managed by RStudio. If you are not using RStudio, they can be difficult to set-up, as they have to be created manually. However, it is possible to use renv without an R project, as discussed in this GitHub issue. This can be done by using setwd() to set your repository as the current working directory, and then continuing with the steps below, running renv::init().


Initialise renv. In your R console:

renv::init()

This creates:

  • renv/: stores packages for the project.
  • renv.lock: records packages and the exact versions used.
  • .Rprofile: ensures renv activates when the project opens.


With renv initialised, you will now have an empty project library, just containing renv, as you can see from viewing renv.lock (example below). This is isolated from your previous projects, and from here, you can install the packages relevant for your current project.

Example renv.lock:

{
  "R": {
    "Version": "4.4.1",
    "Repositories": [
      {
        "Name": "CRAN",
        "URL": "https://packagemanager.posit.co/cran/latest"
      }
    ]
  },
  "Packages": {
    "renv": {
      "Package": "renv",
      "Version": "1.0.7",
      "Source": "Repository",
      "Repository": "CRAN",
      "Requirements": [
        "utils"
      ],
      "Hash": "397b7b2a265bc5a7a06852524dabae20"
    }
  }
}


2.3 Adding packages to the environment

Add packages to the environment by modifying the environment.yaml file and then running:

conda env update --file environment.yaml --prune

You should specify the exact package versions in you environment.yaml. If you’re starting from scratch, you may not know which versions you need, so you can leave them out initially, as we did in step 1.

However, now that we have built our environment (which used the latest versions as none were specified), it is important to then record your versions in the environment.yaml. These are the versions you saw when running conda list. For example:

name: des-example
channels:
  - conda-forge
dependencies:
  - python=3.13.3
  - simpy=4.1.1

It is possible to simply install packages using renv::install("packagename") or install.packages("packagename").

However, we recommend using a DESCRIPTION file. This is because it allows you to keep a record of the main packages you installed. You’ll generate a clear, readable summary of the main dependencies for your project.

Why use a DESCRIPTION file?

  • Clear requirements. The DESCRIPTION file provides a clear summary of your project’s main pages. This is much easier to read than renv.lock, which lists all the packages and their dependencies, making it cumbersome if you just want to see the key packages.
  • Consistency with package development. If your project is (or might become) an R package, the DESCRIPTION file is the standard way to declare dependencies.
  • Alternative for environment recreation. While renv.lock is the primary tool for restoring the exact environment, having a DESCRIPTION file is a valuable backup. If you encounter issues with renv.lock, you (or collaborators) can use DESCRIPTION to reinstall the main dependencies - with more information on this below in the section on recreating environments.
  • Explicit snapshots. If you want precise control over what is included in renv.lock, a DESCRIPTION file enables you to use “explicit” snapshots. These mean only the packages listed in DESCRIPTION (and their dependencies) are recorded - as is covered below in the step on updating your renv.lock file.


Create a DESCRIPTION file. Run in the terminal:

touch DESCRIPTION

Open the file and copy in the template below. You can customise some of the meta-data (e.g. package, title, authors, description).

This is a standard template. You can create an identical file with usethis by running usethis::use_description(). However, we can just create it from scratch, which helps to minimise our dependencies.

Package: packagename
Title: What the Package Does (One Line, Title Case)
Version: 0.0.0.9000
Authors@R: 
    person("First", "Last", , "first.last@example.com", role = c("aut", "cre"))
Description: What the package does (one paragraph).
License: `use_mit_license()`, `use_gpl3_license()` or friends to pick a
    license
Encoding: UTF-8
Roxygen: list(markdown = TRUE)
RoxygenNote: 7.0.0


List dependencies. In DESCRIPTION, dependencies are listed under two headings:

  • Imports: for required packages.
  • Suggests: for optional/development packages.

For most projects (especially non-packages), it’s fine to just list all your dependencies under Imports for simplicity, as - assuming you’re using the implicit renv snapshot type (described below) - renv will only detect and install packages listed under Imports and used in your scripts (and not necessarily those under Suggests).

The distinction between Imports and Suggests is more relevant when constructing your research as an R package, as it will distinguish between those necessary for the core simulation and those for other analysis and tests.

At the very beginning of your project, your DESCRIPTION file might only include a few packages. For example, if you are starting with just the simmer package, your Imports section would look like this:

Imports:
    simmer

As your project develops and you find yourself using additional packages, simply add each new dependency to the Imports section of your DESCRIPTION file.

If you are following along with this book, you can use the following DESCRIPTION snippet to include all the packages needed to run the provided code in this book:

Imports:
    simmer,
    magrittr,
    dplyr,
    purrr,
    rlang,
    tidyr,
    tidyselect,
    future,
    future.apply,
    ggplot2,
    tibble,
    gridExtra,
    R6
Suggests:
    testthat (>= 3.0.0),
    patrick,
    lintr,
    devtools,
    xtable,
    data.table,
    mockery
Config/testthat/edition: 3

Note: In the R Packages book, they recommend that versions are not specified in DESCRIPTION. Instead, they suggest that no version is specified - or that a minimum version is specified, if you know that an older version of specific package/s would break the code. This is why it is important to also create an renv.lock file (as below), so you do have a record of the exact versions used.


Install packages from DESCRIPTION. Run the following command in your console. This will install the packages from DESCRIPTION, and will determine and install the dependencies of those packages too.

renv::install()


Update renv.lock. To take a snapshot of your environment and update your renv.lock file, run:

renv::snapshot()

This will update the lock file with a full list of the exact packages and dependencies, including the versions you have installed, providing a clear record of your working environment.

There are three snapshot types:

  • Implicit - records any packages (and their dependencies) listed in DESCRIPTION or used in your code.
  • Explicit - only records packages (and their dependencies) listed in DESCRIPTION.
  • All - records all packages in your environment.

The default snapshot type is implicit, and we recommend this approach. This is because it will catch any packages you are using but that you have forgot to add to DESCRIPTION (although it is best to remember to record these in DESCRIPTION, so you have a nice clear list of packages, and don’t have to delve into renv.lock if you’re having issues).

The downside to this snapshot type if that it may include unnecessary packages if you include old scripts in your repository that use packages you no longer need. However, this can be avoided by removing old scripts (good practice!).

If you want to check your snapshot type, run this command in the R console:

renv::settings$snapshot.type()

You can then change it if desired using one of:

renv::settings$snapshot.type("implicit")
renv::settings$snapshot.type("explicit")
renv::settings$snapshot.type("all")


System dependencies

Some R packages require external system libraries. The exact requirements will depend on which packages you use, what operating system you have, and whether you have used R before.

If these system libraries are missing, package installation may fail, even if you have the correct R package versions.

For example, working on Ubuntu, we found that we had to install the following system dependencies for igraph:

sudo apt install build-essential gfortran
sudo apt install libglpk-dev libxml2-dev

You should list any system dependencies that you are aware of in your project’s README or setup instructions.


2.4 Recreating an existing environment

When working on a project from scratch, you will often build up your environment organically and iteratively as you find more packages you want to use. However, to follow along with this book and ensure everything works as expected, you can use the full environment provided below. Copy this into your environment.yaml (feel free to alter the name!):

name: des-example
channels:
  - conda-forge
dependencies:
  - ipykernel=6.29.5
  - jinja2=3.1.5
  - joblib=1.4.2
  - nbconvert=7.16.6
  - nbformat=5.10.4
  - nbqa=1.9.0
  - numpy=2.2.2
  - pandas=2.2.3
  - pip=25.0
  - plotly_express=0.4.1
  - pylint=3.3.4
  - pytest=8.3.4
  - pytest-xdist=3.6.1
  - python=3.13.1
  - rich=13.9.4
  - simpy=4.1.1
  - pip:
    - kaleido==0.2.1
    - sim-tools==0.8.0

Then update your environment to include these packages (after running conda activate des-example) with:

conda env update --file environment.yaml --prune

When you want to recreate an environment—such as for an old project or when collaborating—you have two main options, depending on which files are available:

Method What does it install? Best for…
From renv.lock Installs the exact package versions (and their dependencies) used previously Full reproducibility; restoring the original environment exactly
From DESCRIPTION Installs the main packages listed (and their dependencies), but uses the latest available versions (unless specified) Getting started quickly or if renv.lock is missing or problematic


Restoring from renv.lock (preferred). If the project includes an renv.lock file, use this as your first option. This file records the exact versions of all packages used, enabling you to recreate the environment as it was originally (*except for R version and operating system differences).

To restore the environment, run in your R console:

renv::restore()

This will attempt to install all packages at the precise versions specified.

Occasionally, you may encounter issues - such as conflicts, unavailable packages, or operating system differences - especially with older projects or across different systems.


Rebuilding from DESCRIPTION. If renv.lock is unavailable or causes problems, you can use the DESCRIPTION file. This file lists the main package dependencies, but typically does not specify exact versions (unless you have set minimum versions for specific needs).

To install packages listed in DESCRIPTION, run:

renv::install()

This will install the latest available versions of the listed packages and their dependencies. This approach is less precise than using renv.lock, so results may differ slightly from the original environment, especially if package updates have introduced changes.

In theory, the R ecosystem aspires to maintain backwards compatability, meaning that code written for older package versions should continue to work with newer ones. However, in practice, there is no strict guarantee of backward compatibility in R, either for the core language or for contributed packages.

As discussed in the R packages book:

“If we’re being honest, most R users don’t manage package versions in a very intentional way. Given the way update.packages() and install.packages() work, it’s quite easy to upgrade a package to a new major version without really meaning to, especially for dependencies of the target package. This, in turn, can lead to unexpected exposure to breaking changes in code that previously worked. This unpleasantness has implications both for users and for maintainers.”

Hence, using a lockfile like renv.lock is the only reliable way to ensure that your environment is recreated exactly as it was - but DESCRIPTION can serve as a valuable back-up when this doesn’t work, and otherwise just as a handy summary of the main packages.


If neither file is provided. If you have neither a renv.lock nor a DESCRIPTION file, you can try to create a DESCRIPTION file based on your knowledge of the project and its required packages.

Summary:

We can use renv to create a reproducible environment in R. In the process above, we generated two key files:

  • DESCRIPTION - lists project’s primary packages with any minimum version requirements, but not exact versions.
  • renv.lock - complements this by recording the precise versions of all packages and their dependencies.

These work together to both provide (a) a comprehensive record of your project environment, and (b) enable yourself or others to reconstruct the environment.


3 Other examples

If you’re interested in using one of the other tools for dependency management, we’ve provided some brief information on each below, and direct you to other sources for a more detailed explanation of how to use them.

Installation

As venv is included with the standard Python library, you do not need to install it.


Environment creation

To create a virtual environment, we use the python -m venv <name> command. Typically the environment is just named venv - and so, we just execute:

python -m venv venv

You should execute this from within your project folder. It will create a new folder named venv/ to store the environment within.

venv
├── bin/
├── include/
├── lib/
├── lib64/
└── pyvenv.cfg

It is not recommend to add venv to GitHub. The default Python .gitignore file includes venv/ to ignore the entire folder.

Activation of the virtual environment will differ depending on your operating system.

# Linux or MacOS
source venv/bin/activate
# Windows (from cmd.exe)
venv\Scripts\activate
# Windows (from PowerShell)
venv\Scripts\Activate.ps1

Once activated, the shell prompt changes to indicate that the environment is active - for example:

(venv) (base) amy@xps:~/Documents/stars/venv_test$


Choosing python version

venv cannot control which python version is used, it will just use one on system. You can check what this is by running:

venv/bin/python --version


Adding packages

To add packages, create a requirements.txt file. Within this, list the required packages and their versions.

nbqa==1.9.0
simpy==4.1.1

To install these, with our environment active, run:

pip install -r requirements.txt


Further information

For more guidance on using venv, check out the venv documentation.

Installation

Install poetry following the instructions for your operating system. For example, on Linux:

curl -sSL https://install.python-poetry.org | python3 -

After installation, check that Poetry is available:

poetry --version


Environment creation

From our project directory, we can create a new poetry project by running:

poetry init

This will guide you through a series of prompts to create a pyproject.toml file. You can answer these or just press “Enter” to accept the default values. For example, accepting the defaults can produce something similar to:

[project]
name = "poetry-test"
version = "0.1.0"
description = ""
authors = [
    {name = "amyheather",email = "a.heather2@exeter.ac.uk"}
]
readme = "README.md"
requires-python = ">=3.10"
dependencies = [
]


[build-system]
requires = ["poetry-core>=2.0.0,<3.0.0"]
build-backend = "poetry.core.masonry.api"

When first add a package, the environment will be created.


Choosing python version

To use a specific version of python:

poetry env use 3.11
poetry install

However, it cannot install specific versions for you - this is only choosing between versions already on your machine.


Adding packages

To add dependencies, use the poetry add command (rather than editing pyproject.toml directly). This will install the package, update pyproject.toml and generate a poetry.lock file if one does not already exist.

For example, to add SimPy:

poetry add simpy

This updates pyproject.toml:

[project]
name = "poetry-test"
version = "0.1.0"
description = ""
authors = [
    {name = "amyheather",email = "a.heather2@exeter.ac.uk"}
]
readme = "README.md"
requires-python = ">=3.10"
dependencies = [
    "simpy (>=4.1.1,<5.0.0)"
]


[build-system]
requires = ["poetry-core>=2.0.0,<3.0.0"]
build-backend = "poetry.core.masonry.api"

And creates/updates poetry.lock to record the exact package version installed:

# This file is automatically @generated by Poetry 2.1.3 and should not be changed by hand.

[[package]]
name = "simpy"
version = "4.1.1"
description = "Event discrete, process based simulation for Python."
optional = false
python-versions = ">=3.8"
groups = ["main"]
files = [
    {file = "simpy-4.1.1-py3-none-any.whl", hash = "sha256:7c5ae380240fd2238671160e4830956f8055830a8317edf5c05e495b3823cd88"},
    {file = "simpy-4.1.1.tar.gz", hash = "sha256:06d0750a7884b11e0e8e20ce0bc7c6d4ed5f1743d456695340d13fdff95001a6"},
]

[metadata]
lock-version = "2.1"
python-versions = ">=3.10"
content-hash = "53e967cadef99331a7f895f64ccb1bd8680e6fe09253335b9d88bd4cb3d6d793"

To install a specific version of a package, specify it when adding:

poetry add nbqa==1.9.0


Further information

For more guidance on using poetry, check out the poetry documentation.

Installation

Install for your operating system - for example, on linux:

curl -LsSf https://astral.sh/uv/install.sh | sh

Can check it has installed by running:

uv version


Environment creation

To set up your repository as a uv project, run:

uv init

This creates:

.
├── .python-version
├── README.md
├── main.py
└── pyproject.toml

When you run the python file, it will create the environment:

uv run main.py

>> Using CPython 3.10.14 interpreter at: /home/amy/mambaforge/bin/python3.10
>> Creating virtual environment at: .venv
>> Hello from uv-test!

Whenever you execute uv run, it checks that everything is up-to-date: lockfile matches pyproject.toml, environment matches lockfile. To manually update though, can run:

uv sync


Choosing python version

To change the python version, open the .python-version file (e.g. nano .python-version), then edit the listed version, save, and run uv sync. It will install the specified version of python.


Adding packages

To add packages, run uv add, and can specify versions:

uv add simpy
uv add nbqa==1.9.0

The config files are:

  • pyproject.toml - a simple list of the packages you add with uv add, including any specified versions.
  • uv.lock - full details on every package in the environment.

Example pyproject.toml:

[project]
name = "uv-test"
version = "0.1.0"
description = "Add your description here"
readme = "README.md"
requires-python = ">=3.10"
dependencies = [
    "nbqa==1.9.0",
    "pytest>=8.3.5",
    "simpy>=4.1.1",
]

Example uv.lock:

version = 1
revision = 2
requires-python = ">=3.10"
resolution-markers = [
    "python_full_version >= '3.11'",
    "python_full_version < '3.11'",
]

[[package]]
name = "asttokens"
version = "3.0.0"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/4a/e7/82da0a03e7ba5141f05cce0d302e6eed121ae055e0456ca228bf693984bc/asttokens-3.0.0.tar.gz", hash = "sha256:0dcd8baa8d62b0c1d118b399b2ddba3c4aff271d0d7a9e0d4c1681c79035bbc7", size = 61978, upload-time = "2024-11-30T04:30:14.439Z" }
wheels = [
    { url = "https://files.pythonhosted.org/packages/25/8a/c46dcc25341b5bce5472c718902eb3d38600a903b14fa6aeecef3f21a46f/asttokens-3.0.0-py3-none-any.whl", hash = "sha256:e3078351a059199dd5138cb1c706e6430c05eff2ff136af5eb4790f9d28932e2", size = 26918, upload-time = "2024-11-30T04:30:10.946Z" },
]

...


Further information

For more guidance on using uv, check out the uv documentation.

Installing and managing R versions

The following instructions are for Linux systems. If you are using Windows or Mac, download the R installer from CRAN. To manage multiple versions on Windows, consider RSwitch utility or manually adjust your PATH environment variable. On Mac, consider RSwitch for Mac, or use Hojmebrew to install specific versions and manage symlinks.


Installation

Following instructions from r-builds, we first specify the version of R that you want to install (see available versions).

R_VERSION=4.5.0

Download the .deb package (modifying the url depending on your system - ubuntu-2004, ubuntu-2204, ubuntu2404, debian-12).

curl -O https://cdn.posit.co/r/ubuntu-2204/pkgs/r-${R_VERSION}_1_amd64.deb

Install the package:

sudo gdebi r-${R_VERSION}_1_amd64.deb

View installed R versions:

ls /opt/R/


Switching between versions

To set the default R version for RStudio and the terminal, you can create symbolic links in /usr/local/bin pointing to the desired version under /opt/R.

sudo ln -s /opt/R/${R_VERSION}/bin/R /usr/local/bin/R 
sudo ln -s /opt/R/${R_VERSION}/bin/Rscript /usr/local/bin/Rscript

However, a better approach is to use update-alternatives. You have to register R and Rscript for each version of R - for example:

sudo update-alternatives --install /usr/local/bin/R R /opt/R/3.6.0/bin/R 360
sudo update-alternatives --install /usr/local/bin/Rscript Rscript /opt/R/3.6.0/bin/Rscript 360

sudo update-alternatives --install /usr/local/bin/R R /opt/R/4.4.1/bin/R 441
sudo update-alternatives --install /usr/local/bin/Rscript Rscript /opt/R/4.4.1/bin/Rscript 441

sudo update-alternatives --install /usr/local/bin/R R /opt/R/4.5.0/bin/R 450
sudo update-alternatives --install /usr/local/bin/Rscript Rscript /opt/R/4.5.0/bin/Rscript 450

Then run the following commands to switch versions interactively - you’ll be prompted to select which version of R to use.

sudo update-alternatives --config R
sudo update-alternatives --config Rscript

When you open RStudio, you should find it has switched to the version of R you chose.

However, if using different versions of R between projects, you will need to change this before opening RStudio for each project.

Installation

Follow installation instructions for your operating system. For example, on Linux Ubuntu:

`which sudo` curl -L https://rig.r-pkg.org/deb/rig.gpg -o /etc/apt/trusted.gpg.d/rig.gpg
`which sudo` sh -c 'echo "deb http://rig.r-pkg.org/deb rig main" > /etc/apt/sources.list.d/rig.list'
`which sudo` apt update
`which sudo` apt install r-rig

Then, to confirm it has installed:

rig --version


See current R versions

To see all R versions installed on machine:

rig list

Example output:

* name   version  aliases
------------------------------------------
  3.6.0           
  4.2.2           
  4.3.1           
  4.4.1           
  4.5.0  


Add new R versions

Can add specific versions:

rig add 4.1.2

Or just the latest version:

rig add


Choose which R version to use

Use the rig default command to choose an R version - when you open RStudio, it will be active. It will override the version you have set manually - but redoing that (e.g. with update-alternatives) will override it back.

Example:

rig default 4.1.2


Further information

See the rig GitHub repository for further information on using it.

Using specific R version and packages for each project

Installation

Follow the installation instructions for your operating system. For example, on linux:

curl -sSL https://raw.githubusercontent.com/A2-ai/rv/refs/heads/main/scripts/install.sh | bash

We can then check it has installed by running:

rv --version


Setting up the project with a particular version of R

To set up rv project, execute from terminal rv init. However, if you wish to use a particular version of R, you should also specify this when setting up the project.

Whilst rv will not install new versions of R for you, you can fix each project to a particular version of R, and it will then warn/error if the running version of R does not match this.

For example, setting up a project fixed to R 4.5:

rv init --r-version 4.5

This will create:

.
├── .Rprofile
├── rproject.toml
└── rv/
    ├── .gitignore
    └── scripts/
        ├── activate.R
        └── rvr.R

You can view a summary of the environment by running:

rv summary

If you try to do this without that version of R installed, the project will initialise successfully, but running rv summary you will see an error message similar to:

Failed to get R version

Caused by:
    Specified R version (4.5) does not match any available versions found on the system (3.6.0, 4.2.2, 4.3.1, 4.4.1)


Setting repositories

When we ran rv init, we got an error message:

WARNING: Could not set default repositories. Set with your company preferred package URL or public url (i.e. `https://packagemanager.posit.co/cran/latest`)

To resolve this, we opened rproject.toml and amended the repositories section to list CRAN:

repositories = [
    {alias = "CRAN", url = "https://cran.r-project.org", force_source = true}
]

Without this change, it was not possible to install packages (would “fail to resolve all dependencies”).


Adding packages

To add packages, simply run rv add <package>. This will install the specified package, and update the rproject.toml file to list it as a dependency, and add all installed packages to an rv.lock file. For example, if we run:

rv add simmer

The rproject.toml dependencies section updates to:

dependencies = [
    "simmer",
]

An rv.lock file is created:

# This file is automatically @generated by rv.
# It is not intended for manual editing.
version = 2
r_version = "4.5"

[[packages]]
name = "Rcpp"
version = "1.0.14"
source = { repository = "https://cran.r-project.org/" }
force_source = true
dependencies = []

[[packages]]
name = "codetools"
version = "0.2-20"
source = { builtin = true }
force_source = false
dependencies = []

[[packages]]
name = "magrittr"
version = "2.0.3"
source = { repository = "https://cran.r-project.org/" }
force_source = true
dependencies = []

[[packages]]
name = "simmer"
version = "4.4.7"
source = { repository = "https://cran.r-project.org/" }
force_source = true
dependencies = [
    "Rcpp",
    "magrittr",
    "codetools",
    { name = "Rcpp", requirement = "(>= 0.12.9)" },
]


Adding specific versions of packages

Currently, rv requires this is done by editing the rproject.toml file and then running:

rv sync

I found this a bit hit-or-miss - several packages I tried failed to install due to issues fetching dependencies like glue. However, these two examples of using simmer 4.4.6.4 (instead of the latest 4.4.7) worked fine - either installing from CRAN or GitHub:

dependencies = [
    {name = "simmer", url = "https://cran.r-project.org/src/contrib/Archive/simmer/simmer_4.4.6.4.tar.gz"},
]
dependencies = [
    {name = "simmer", git = "https://github.com/r-simmer/simmer.git", tag = "v4.4.6.4"},
]


Further information

Check out the rv GitHub repository for more advice on using this tool, and the latest instructions (as this package is still in active development).


4 Further information