Literate Analysis with Quarto

TipLearning Objectives

After completing this session, you will be able to:

  • Describe the concept of literate analysis and how it supports reproducible data science
  • Format prose (non-code) text in a Quarto document using Markdown syntax
  • Incorporate functional code chunks into a Quarto document and customize their output
  • Build and render a complete example analysis

1 Introduction to Literate Programming

Traditional code is written for computers - it can be hard for humans to follow, even the person who wrote it. In 1984, computer science pioneer Donald Knuth proposed flipping this around: rather than instructing a computer, write code that explains your thinking to other people.

“Instead of imagining that our main task is to instruct a computer what to do, let us concentrate rather on explaining to human beings what we want a computer to do.” - Donald Knuth, 1984

In a literate analysis, we weave together natural-language prose (describing your goals, methods, and interpretations) with functional code (that actually performs the analysis). The result renders into a polished HTML, PDF, or Word report - a single document that is both human-readable and fully reproducible.

2 Quarto and Literate Programming

Quarto is an open-source publishing system that makes literate analysis straightforward. A Quarto file (.qmd) mixes formatted prose with executable code chunks, and renders them together into a complete report.

TipCoding languages in Quarto

We will focus on using Quarto with R code, but it is designed to work seamlessly with other coding languages as well, including Python, Julia, and Observable JavaScript. You can even use multiple languages in the same document.

NoteQuarto vs. RMarkdown

If you’ve used RMarkdown (.Rmd) before, Quarto (.qmd) will feel familiar. The main differences are that Quarto has richer multi-language support and improved formatting options. Both formats share the same three-part structure: YAML, prose, and code chunks.

2.1 Why does this matter for reproducibility?

When your entire analysis - data loading, cleaning, statistics, and figures - lives in one Quarto document, you can re-run everything with a single click. If the data updates, so does your report. This eliminates error-prone copy-pasting between scripts, spreadsheets, and documents, and gives collaborators (and your future self!) a clear trail from raw data to final results.

3 Structure of a Quarto Document

Every Quarto document has three components:

YAML header - metadata at the very top of the file, enclosed in ---. It controls the document title, author, output format, and a lot more.

---
title: "My Analysis"
author: "Your Name"
format: html
---

Prose - plain text written in Markdown (the white areas of the document).

## Introduction

In this literate analysis, we:

*  Load the data
*  Calculate summary statistics
*  Plot the results

... etc

Code chunks - executable code blocks (the grey areas), opened with ```{r} and closed with ```.

```{r}
x <- "Hello world!"
y <- 1 + 1
```

4 Let’s Create A Quarto Document

  1. In RStudio, go to File New File Quarto Document.
  2. Give it a title (e.g., “Introduction to Quarto”), leave the other options as-is, then click Create.
  3. Look at what you get: a YAML header at the top, with title and format, and perhaps some example content below.
  1. In Positron, go to File New File Quarto Document.
  2. Look at what you get: a YAML header at the top for title and format, and perhaps some example content below.
  3. Fill in the title (e.g., “Introduction to Quarto”)

Below the YAML header, if your default is a blank canvas, let’s add some content. Type or copy/paste so your document looks like more or less like this:

---
title: "Untitled"
format: html
---
## Quarto

Quarto enables you to weave together content and executable code into a finished document. To learn more about Quarto see <https://quarto.org>.

## Running Code

When you click the **Render** button a document will be generated that includes both content and the output of embedded code. You can embed code like this:
```{r}
1 + 1
```
You can add options to executable code like this 
```{r}
#| echo: false
2 * 2
```
The `echo: false` option disables the printing of code (only output is displayed).

Click the Render button. You will be asked to save first - give it a useful name (e.g., quarto_test.qmd) and save it in your scripts/ folder.

You’ll see an HTML file appear in your browser. Notice:

  • The first code chunk (1 + 1) runs and displays its result.
  • The second chunk shows the result but not the code - that’s because it includes the code chunk option #| echo: false. More on these later!

4.1 YAML header

The YAML header (top of page, everything between the two --- lines) is metadata with information on the document and instructions on how to render it. There are way too many options to list, but a few common options include:

---
title: "My Analysis"
author: "Your Name"
format: 
  html:
    toc: true
    number-sections: true
execute:
  message: false
  warning: false
---
1
Output format (html, pdf, docx, etc.)
2
Include a table of contents in the HTML output
3
Number section headers in the HTML output
4
Suppress messages from all code chunks by default (can be overridden in individual chunks)
5
Suppress warnings from all code chunks by default (can be overridden in individual chunks)

Unlike in R, indentation is critical in YAML to show which lines are subsets of other lines. If your document doesn’t render because of YAML errors, check the spacing and indents!

TipStandalone HTML Outputs!

By default when rendering a Quarto document as HTML, Quarto tends to save output images separately from the HTML file, along with CSS resources and other information. This can make it difficult to share the HTML file with collaborators, since the images (etc.) won’t be included. In the format: portion of the YAML header, use the embed-resources option to make a self-contained HTML with all resources embedded, for easier sharing:

format:
  html:
    embed-resources: true

4.2 Markdown Syntax

The prose sections of a Quarto document use Markdown, a lightweight formatting language with only a few basic rules to learn. Markdown is also used in GitHub READMEs, Slack, and many other tools, so it’s well worth knowing.

Syntax Result
# Heading 1 Large top-level header
## Heading 2 Smaller sub-header
**bold** bold
*italic* italic
[link text](url) Hyperlink
* item Bullet list
1. item Numbered list

For a full reference, see https://www.markdownguide.org/cheat-sheet/.

Tip

The # symbol means something different in R code (a comment) vs. Markdown (a header). In Markdown, the number of # symbols you use matters: # is the biggest header, ### up to ###### are consecutively smaller and nested below it.

ExerciseExercise 1

Add some italic text, a numbered list, and a sub-header to your document. Try a few other Markdown syntax options. Re-render and check the output.

4.3 Visual vs. Source Editor

Quarto includes a Visual Editor that lets you format text visually, like a word processor. While we recommend learning raw Markdown (Source Editor) - since you’ll use it in many other contexts - the Visual Editor has two genuinely useful features:

  • Citations: Go to Insert > Citation, choose a source (e.g., paste a DOI), and Quarto automatically formats the citation, creates a references.bib file, and updates your YAML header. Done.
  • Tables: Markdown tables are tedious to type by hand. Use the Table menu to insert and edit them visually.

To toggle between Visual Editor and Source Editor mode:

  • RStudio: Click the “Visual” button (vs. “Source”) at the top right of the editor pane.
  • Positron: Command-Shift-F4 (Mac) or Ctrl-Shift-F4 (Windows).
ExerciseExercise 2

Enable Visual Editor mode.

Add a citation (e.g., DOI 10.1038/s41467-020-17726-z) into a section of prose in your Quarto document, using the Visual Editor.

Add a table into your Quarto document using the Visual Editor.

Toggle back to Source Editor mode. Look at the raw Markdown and BibTeX that was generated for your citation and table.

Render the document and check the differences in the output.

4.4 Code Chunks in Quarto

Code chunks contain functional code to be executed. Markdown syntax will not work here! You can create a new chunk in your Quarto in one of these ways:

  • Go to Code in the top menu bar, click “Insert Chunk”
  • Use the keyboard shortcut
    • RStudio: Mac: Command-Option-i or Windows: Ctrl-Alt-i
    • Positron: Mac: Command-Shift-i or Windows: Ctrl-Shift-i
  • Type by hand:
```{r}

```

4.4.1 Executing Code Chunks in Interactive Mode

All the R code in your Quarto document will execute when you Render the document, but you can also run it on the fly (“interactive” mode) to test and debug it as you write.

Here are a few of the options to run code interactively:

  1. Select the line (or simply put the cursor there), and click “Run”. This is available from:
    1. the bar above the file (green arrow)
    2. the menu bar: Code > Run Selected Line(s)
    3. keyboard shortcut: Command-Enter or Ctrl-Enter
  2. Click the green arrow at the right of the code chunk to run the entire chunk.

Here are a few of the options to run code interactively:

  1. Select the line (or simply put the cursor there), and use the keyboard shortcut: Command-Enter or Ctrl-Enter
  2. Click the Run Cell arrow above the code chunk to run the entire chunk.

ExerciseExercise 3

Add a code chunk to your Quarto document, with some calculations and variable assignments. For example:

```{r}
x <- 4 * 8

hights_ft <- c(5.2, 6.0, 5.7)

coef <- 3.14
```

Run the code in interactive mode, and examine the values in the Environment pane ( RStudio) or Session Variables pane ( Positron).

4.4.2 Code chunk options

Here are some common options available to customize code chunk outputs.

Option What it does
#| eval: false Don’t run the code (just display it)
#| echo: false Run the code, but hide it from the output
#| message: false Suppress diagnostic messages
#| warning: false Suppress warning messages
#| include: false Run the code silently - no output shown at all
#| fig-width: 6 Set the width (or height) of a plot (in inches)
#| fig-align: center Set the alignment of a plot (left, right, center)

Options can be combined. For example, an exploratory chunk you don’t want in your final report:

```{r}
#| eval: false
#| echo: false
summary(my_data)
```
1
Don’t evaluate/run the code
2
Don’t display the code in the rendered output

Many more code chunk options can be found at Quarto.org.

5 Practice: Literate Analysis with Ocean Water Samples

Let’s build a simple but complete literate analysis in Quarto using real data. We are going to work with seawater chemistry data, BGchem2008data.csv, downloaded from the Arctic Data Center.

5.1 Get The Data!

If you don’t already have this data, download it to the appropriate location:

  1. Navigate to this dataset by Craig Tweedie that is published on the Arctic Data Center. Craig Tweedie. 2009. North Pole Environmental Observatory Bottle Chemistry. Arctic Data Center. doi:10.18739/A25T3FZ8X.
  2. Find the csv file called BGchem2008data.csv and click the “download” button next to the file.
  3. Find the downloaded file on your computer and move it to the data directory in your R project.
  4. Check your file was successfully relocated by navigating into your data folder in the Files pane.
  1. Navigate to this dataset by Craig Tweedie that is published on the Arctic Data Center. Craig Tweedie. 2009. North Pole Environmental Observatory Bottle Chemistry. Arctic Data Center. doi:10.18739/A25T3FZ8X.
  2. Find the csv file called BGchem2008data.csv and click the “download” button next to the file.
  3. Click the “Upload” button in your RStudio server file browser.
  4. In the dialog box, make sure the destination directory is the data directory in your R project, click “Choose File,” and locate the BGchem2008data.csv file. Press “OK” to upload the file.
  5. Check your file was successfully uploaded by navigating into your data folder in the Files pane.

5.2 A Better Workflow for Writing Literate Analyses

Experienced R users sometimes struggle to transition to Quarto because writing prose and code at the same time feels unfamiliar. A helpful approach:

  1. Block out your high-level sections as Markdown headers.
  2. Add bullet points as pseudo-code for what each section needs to do.
  3. Fill in the actual code under each bullet, then convert the bullets to prose.
ExerciseExercise 4

For this analysis, create a new Quarto document; delete anything below the YAML header and structure your document like this, using Markdown headers:

  • Introduction
    • About the Data
  • Setup
    • Read in data
  • Analysis
    • Summary Statistics
    • Redfield Ratio
    • Plot
  • Conclusion

Under “About the Data”, write a sentence describing the dataset with a hyperlink to its source, and note when it was downloaded.

5.3 Setup: Loading Packages

Add a code chunk under your Setup header to load the packages you’ll need:

```{r setup}
library(readr)
library(here)
```
1
readr package to read files, including read_csv()
2
here package to build file paths relative to your project root
TipBest Practice!

Put all library() calls (or other package management, e.g., librarian::shelf()) in one chunk near the top of your document so collaborators immediately know what packages to install.

TipAnother Best Practice!

Name your code chunks for easy searching (such as {r setup} above), and R will display the names so you can track progress as the Quarto document renders!

5.4 Read In Data

Create a new code chunk under “Read in data” (and give it a helpful name!). Use read_csv() with here() to load your data. The here() function builds file paths relative to your project root, which keeps things reproducible regardless of where your .qmd file lives within the project (including if you move it to a new location within the project!).

bg_chem <- read_csv(here::here("data/BGchem2008data.csv"))
Rows: 70 Columns: 19
── Column specification ────────────────────────────────────────────────────────
Delimiter: ","
chr   (1): Station
dbl  (16): Latitude, Longitude, Target_Depth, CTD_Depth, CTD_Salinity, CTD_T...
dttm  (1): Time
date  (1): Date

ℹ Use `spec()` to retrieve the full column specification for this data.
ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
ExerciseExercise 5

read_csv() prints a column specification message when it runs. How would you suppress this from appearing in your rendered output?

Check the code chunk options above! Alternately, check the documentation for read_csv() (i.e., ?read_csv) to see an option for suppressing this behavior!

5.5 Explore Your Data

Before any analysis, get familiar with the data. Create a chunk with #| eval: false and #| echo: false for exploratory code you don’t want in the final report:

#| eval: false
#| echo: false
colnames(bg_chem)
str(bg_chem)
head(bg_chem)
summary(bg_chem)

You can also type View(bg_chem) directly in the console to browse the data in a table.

5.6 Calculate summary statistics

The Redfield ratio is the consistent 16:1 ratio of nitrogen to phosphorous found in marine phytoplankton. Let’s see how our Arctic data compare.

First, calculate mean values for the key variables:

nitrate <- mean(bg_chem$NO3)
nitrite <- mean(bg_chem$NO2)
amm     <- mean(bg_chem$NH4)
phos    <- mean(bg_chem$P)

Then calculate the ratio:

ratio <- (nitrate + nitrite + amm) / phos

5.7 Report Result with Inline R code

You can embed R results directly in your prose using backtick syntax: `{r} round(ratio)`. For example, write this in your document:

The Redfield ratio for this dataset is approximately `{r} round(ratio)`.

It will render as: The Redfield ratio for this dataset is approximately 6.

This is much better than evaluating code, copying a number, and pasting it into your text - especially when data changes.

5.8 Plot the data

Finally, create a simple plot of individual measurements:

plot(bg_chem$P, bg_chem$NO2 + bg_chem$NO3 + bg_chem$NH4)

ExerciseExercise 6

Decide whether you want the plot code to appear in the rendered output alongside the figure, and add the appropriate chunk option. Then render your document.

6 FAQuarto

6.1 Quarto and Environments

Quarto renders documents in a fresh R environment - completely separate from your interactive RStudio session. This is what makes Quarto so powerful for reproducibility, but it can also cause confusion.

Try this:

  1. Restart your R session (Session > Restart R).
  2. Try running just the last code chunk (the plot). You’ll get an error because bg_chem doesn’t exist yet.
  3. Now use Run > Run All to run chunks in order - this works.
  4. Finally, click Render. Notice that the environment pane is empty afterward, even though the document rendered successfully.

When you press Render, RStudio spins up a fresh session, runs everything top-to-bottom, generates the output, then closes. This is a feature: it forces your document to be self-contained. A common gotcha is running library() in the console during development but forgetting to include it in the document - Render will fail because the fresh environment doesn’t have that package loaded.

6.2 Reproducibility!

If your document renders successfully, it’s reproducible. Get into the habit of rendering regularly during development.

6.3 When to Use R Scripts vs. Quarto

Quarto doesn’t replace R scripts - both have their place.

  • Use Quarto for analyses you want to explain, share, or publish: the code, results, and interpretation all belong together.
  • Use R scripts for reusable utility functions, repetitive data cleaning steps that don’t need much explanation, or code you’ll source() from multiple projects.

In practice, a single project often has both: helper scripts stored in a folder, and a primary .qmd that sources those scripts and presents the analysis narratively.

6.4 Additional Resources

6.5 Troubleshooting: Can’t Render to PDF?

PDF rendering requires a LaTeX installation. If you don’t have one, the easiest fix is tinytex (type this in the R Console, not a script):

install.packages("tinytex")
tinytex::install_tinytex()

If you get a permissions error (destination /usr/local/bin not writable), run this in the Terminal first:

sudo chown -R `whoami`:admin /usr/local/bin

Then try the install again. See TinyTeX’s documentation for more.