Want to share your content on R-bloggers? click here if you have a blog, or here if you don't.
Introduction
In previous posts I have described how to use the self-contained Python scripts feature in the uv Python package manager to create virtual environments to render Quarto documents using the Jupyter nbstata kernel and the python3 kernel. In this post I describe how to do the same for R scripts to render Quarto documents running R code using the knitr engine.
I recently discovered that there are now three uv-inspired package managers for R; ir, uvr, and rv (… maybe there are more?). I will concentrate on the first two because they allow defining self-contained R scripts. I find self-contained scripts a fast and lightweight way to define project dependencies, and I very rarely require a record of the exact package versions.
In the following examples I assume we are creating an R script, render.R, which contains one or more calls to quarto::quarto_render() for a lecture or tutorial. For the dependency R packages I include the packages the document itself needs, plus the quarto and knitr packages.
Example self-contained R script using ir
To define dependencies for ir, at the top of the script begin each comment line with #| then write a list under a packages key as follows – this is the list of packages I require for one of my practicals on missing data.
#| packages: #| - gtsummary #| - haven #| - tidyverse #| - VIM #| - quarto #| - knitr # Rest of R code follows ... # ... essentially one or sometimes multiple quarto::quarto_render() calls
This script can be run with
ir run render.R
Example self-contained R script using uvr
uvr follows the same dependency syntax as uv. Each line begins with a # comment, and the dependencies are defined as a TOML array of strings between # /// script and # ///. So the top of our render.R script looks as follows.
# /// script # dependencies = [ # "gtsummary", # "haven", # "tidyverse", # "VIM", # "quarto", # "knitr", # ] # /// # Rest of R code follows ... # ... essentially one or sometimes multiple quarto::quarto_render() calls
This script can be run with
uvr run render.R
Automation with just in a complex directory structure
For each course I teach I have the lecture or tutorial in a subdirectory. To run each script I could run the shell commands given above. To slightly improve efficiency I find that putting the following
justfile at the top of the directory structure saves a bit of typing. The first recipe, render, uses my system R library, the others resolve packages via ir/uvr.
render dir=invocation_directory():
cd "{{ dir }}" && Rscript render.R
ir dir=invocation_directory():
cd "{{ dir }}" && ir run render.R
uvr dir=invocation_directory():
cd "{{ dir }}" && uvr run render.R
I can simply type just ir or just uvr to render the lecture/tutorial given whichever directory I’m in.
Bonus 1 – Example self-contained Quarto document using ir
ir cleverly allows us to alternatively define the dependencies within the YAML header of a Quarto document, under an ir key. In this case we can remove the quarto package as we might assume we’d render this document by clicking the Render button in RStudio or using quarto render ... in the terminal.
---
title: My lecture/tutorial
ir:
packages:
- gtsummary
- haven
- tidyverse
- VIM
- knitr
---
Rest of Quarto document follows ...
Say this Quarto document is tutorial.qmd we would then render it with
ir render tutorial.qmd
More details are given in the ir Quarto docs.
Bonus 2 – Making the R script executable
With both
ir and uvr (and indeed
uv) we can optionally make the render.R script executable, say renaming to simply render, by adding the relevant shebang to the very top of the file.
For ir we add
#!/usr/bin/env -S ir run
and for uvr we add
#!/usr/bin/env -S uvr run
We then make the script executable
chmod +x render
and run it with
./render
Summary
I have shown how to make a self-contained, and optionally executable, R script to render Quarto documents using the knitr engine which automatically manages the required R packages. This functionality is provided by both the ir and uvr R package managers. This approach would also work for RMarkdown documents (of course one would need to swap the quarto package for the rmarkdown package in the list of dependencies).
R-bloggers.com offers daily e-mail updates about R news and tutorials about learning R and many other topics. Click here if you're looking to post or find an R/data-science job.
Want to share your content on R-bloggers? click here if you have a blog, or here if you don't.
