Reproducible R Reports with Quarto and renv
Edited by Dev Kilaru, Senior Data Analyst. How we make our content
Introduction
An analysis is only useful if someone, including you next quarter, can rerun it and get the same answer. Quarto lets you write text and R code in one document and produces a finished report with the numbers and charts generated directly from the data, so nothing is copied and pasted by hand. Combined with an RStudio Project, a random seed, and the renv package for locking package versions, you can hand a colleague a folder that reproduces your results.
Prerequisites
- R and RStudio from the first lesson
- Quarto, which is included with recent RStudio versions and also available from quarto.org
Step-by-Step Guide
Step 1: Create a Quarto document
In RStudio choose File, New File, Quarto Document. A Quarto file has the extension .qmd and has three parts. A YAML header between lines of three dashes sets the title, author, and output format. Plain Markdown text forms the narrative. Code chunks, fenced by triple backticks and marked with an r in curly braces, hold R code that runs when the document is rendered, with the results inserted below each chunk. R Markdown, with .Rmd files, works in nearly the same way and you will meet it in older projects.
---
title: "Fuel Economy Report"
author: "Your Name"
format: html
---
## Summary
```{r}
#| echo: false
library(tidyverse)
avg <- mtcars |> summarise(mpg = mean(mpg))
```
The average car in the dataset gets `r round(avg$mpg, 1)` miles per gallon.Step 2: Control what appears with chunk options
Chunk options go at the top of a chunk as comments starting with a hash and a vertical bar. Setting echo to false hides the code but shows the output, which suits a report for non-programmers. Setting eval to false shows code without running it, and warning and message set to false hide noisy package messages. A fig-cap option adds a caption to a figure, and giving each chunk a label makes errors easier to locate. Show code in documents written for other analysts, and hide it in executive summaries.
```{r}
#| label: mpg-plot
#| echo: false
#| fig-cap: "Fuel economy falls as weight increases."
ggplot(mtcars, aes(wt, mpg)) + geom_point() + theme_minimal()
```Step 3: Render the document
Click Render in RStudio, or run quarto render from a terminal. Quarto executes every chunk from top to bottom in a fresh R session, which is exactly the check you want: if the document renders, the analysis does not depend on anything you did by hand earlier. The same source can produce HTML, a PDF through LaTeX or Typst, or a Word file by changing the format line. HTML is the easiest to share, and an option such as embed-resources set to true packs everything into a single file you can email.
quarto render report.qmd
quarto render report.qmd --to docxStep 4: Put results into the text with inline code
Typing a number into a sentence guarantees that it goes stale when the data changes. Inline code solves this: a short R expression written inside single backticks, starting with the letter r, is replaced by its value when the document renders. Use it for counts, means, dates, and percentages, with round or format to control the display. When the underlying data is refreshed, the narrative updates itself.
We analysed `r nrow(mtcars)` cars. Manual transmissions averaged
`r round(mean(mtcars$mpg[mtcars$am == 1]), 1)` miles per gallon.Step 5: Make randomness repeatable
Anything that uses random numbers, such as sampling rows, splitting data for modeling, or simulations, gives different results on each run. Call set.seed with any integer before the random step so the sequence is the same every time. Set it once near the top of the document and again before any step you want to reproduce exactly. Record the seed in the report so a reader knows how to repeat it.
set.seed(42)
sample(1:100, 5) # the same five numbers every run
train_rows <- sample(nrow(mtcars), 24)Step 6: Lock package versions with renv
Package updates can change results or break code. The renv package gives each project its own private library and records the exact versions in a file named renv.lock. Run renv::init once in the project to start, renv::snapshot after you install or update packages to record the current state, and renv::restore on another computer to install the same versions. Commit renv.lock to version control with your code. Finish by calling sessionInfo or reporting the R version in the document, so readers know the environment.
install.packages("renv")
renv::init() # create a private library for this project
renv::snapshot() # record package versions in renv.lock
renv::restore() # on a new machine: reinstall those versions
sessionInfo()FAQs
- What is the difference between Quarto and R Markdown?
- Quarto is the newer system from the makers of RStudio. It uses nearly the same syntax but works with Python, Julia, and Observable as well as R, and has consistent features for books, websites, and presentations. R Markdown remains supported and many existing projects use it.
- Why does my document render in RStudio but fail on another computer?
- The usual causes are an absolute file path, a package that is not installed, or an object that exists only in your own session. Use project-relative paths, record dependencies with renv, and render from a clean session to find the hidden dependency.
- Should I commit the rendered HTML to version control?
- Commit the source files, your .qmd documents, scripts, and renv.lock. Rendered output can be regenerated, so keep it out of version control unless you publish it, for example to a documentation site.
Summary
You can now produce a report that regenerates its own numbers and charts, control what readers see with chunk options, embed results in the narrative with inline code, make random steps repeatable with set.seed, and freeze your package versions with renv. Together with the earlier lessons on data frames, dplyr, ggplot2, and modeling, this completes the path from first install to a shareable, reproducible analysis.
Related tutorials
- Schedule and Debug Shell Scripts: cron, bash -x, and Portability
- Shell Scripting Project: A Backup Script with Rotation and a Log Report
- Writing Safe Bash Scripts: set -euo pipefail, getopts, and trap
- Shell Pipes, Redirection, grep, sed, and awk for Text Processing
- Bash Loops, Arrays, and Functions Explained
Comments
Log in or create a free account to join the discussion.