Quarto Reports
Every Monday, Priya, a data analyst at the Inkwell Books chain, ships the same thing: last week's sales report. For a long time she did it by hand. She ran her R code, copied the numbers into a Word document, pasted a chart, and wrote a summary sentence. Then one Monday the data changed at the last minute. She updated the chart but forgot the sentence, and the report went out with a headline that said one revenue and a chart that showed another.
That mistake has a name: copy-paste drift, and it is exactly what this lesson removes. With Quarto (and its older sibling R Markdown), the prose, the code, and the figures all live in one file. You render that file once and every number in the text is computed by R, never typed. Then you make it a template that re-runs for any store or any week, with no editing at all.
The widget below is Priya's report. Toggle between Source (.qmd), the plain text she writes, and Rendered, the finished page R produces from it.
By the end of this lesson you will be able to:
- Name the three parts of a Quarto document (the YAML header, the prose, and the code chunks) and say what "render" does
- Write a code chunk and an inline expression so a figure, a table, or a number is produced by R, not pasted
- Explain why this makes a report reproducible: change the data once and every number re-flows
- Describe what render turns your file into, and get HTML, PDF or Word from the same source
- Parameterize a report with
params:so one template re-runs for any input
Prerequisites: you can run R and load a package with library(), you have built a basic ggplot (data, then aes(), then a geom) in The Grammar of Graphics, and you know the dplyr verbs filter() and summarise() from The dplyr Verbs. Every new term is defined as it appears.
One file, three parts
A Quarto document is a single plain text file with the extension .qmd (Quarto markdown). It is not an app and not a server. You write it, then you render it: render means "run the file and produce a finished document," a web page, a PDF, or a Word file. R Markdown (.Rmd) works the same way and Quarto is its modern successor, so everything here applies to both.
Every .qmd is made of just three kinds of content. Toggle the widget above between Source and Rendered and you can see all three:
- The YAML header: a small settings block at the very top, fenced by
---lines. It holds the title, the author, and the outputformat:. (YAML is just a simplekey: valuetext format for settings.) - The prose: ordinary markdown text, headings, sentences, lists, the words a reader actually reads.
- The code chunks: blocks of R fenced by ```
`{r}```. When you render, R runs each chunk and drops its result, a table or a chart, straight into the document.
Everything in this lesson is built from Priya's six Inkwell Books stores. Each lesson runs in a fresh R session, so we create that data right here (run this once, and every later block can use it):
A code chunk runs, and its output appears
A code chunk is the engine of a reproducible report. You write the R once; at render time it executes and its output, a table or a figure, lands in the document in place. Nothing is screenshotted, nothing is pasted.
Here is the table chunk for Priya's report. The pipe |> feeds sales into arrange(desc(revenue)), which sorts the stores from highest revenue down, and knitr::kable() turns a data frame into a clean report table:
And here is the figure chunk, the same bar chart you saw on the cover. In the .qmd this is just another ``` `{r} ``` block; render runs it and inserts the plot:
The report you ship contains the output of these chunks, not the code (you can hide the code with a chunk option). Change a sales figure and re-render, and the table and the chart both redraw themselves.
Inline code: numbers written by R
The table and the chart are computed. But what about a sentence like "Total revenue last week was $31,000"? If Priya types that number, she is back to copy-paste drift the moment the data changes. The fix is inline code: a tiny R expression embedded inside the prose that is replaced by its result when the report renders.
Run this to see exactly the value that would be slotted into the sentence:
In a real .qmd, the prose itself carries the expression. You write inline R between backticks (` r expr `) right in the sentence, and render swaps in the result:
Total revenue last week was $`r sum(sales$revenue)`,
led by `r sales$store[which.max(sales$revenue)]`.
Change one number, then re-render
Priya discovers last week's Airport revenue was entered wrong. She fixes that single number in the sales data and re-renders the report. Which parts of the finished report change?
Write the inline number
Priya's summary needs a sentence: "We sold ___ books last week." That blank should be filled by R, not typed, so it stays correct when the data changes. Write the expression that totals the units column across all six stores.
Show answer
books_sold <- sum(sales$units)
books_sold
#> [1] 1550What render actually does
When you render a .qmd, three things happen in order, and knowing them demystifies the whole process. Knit (sometimes called "execute") runs every code chunk and captures its output. The document, now full of real results, becomes plain markdown. Then a tool called Pandoc converts that markdown into your chosen output format. The result is one self-contained file you can email or host anywhere.
You trigger all of that with one command. From the Terminal, or from R, you point Quarto at the file:
library(quarto)
# in the Terminal:
quarto render weekly-report.qmd
# or from R:
quarto::quarto_render("weekly-report.qmd")
Render runs R once, on your machine, and bakes the results into the output file. The person reading the finished HTML or PDF does not need R installed; they just open the document.
One source, two outputs
Priya needs her report two ways: as a web page for the team wiki, and as a Word document her manager can mark up with comments. She has one .qmd already written. What does she change to get both?
format: changes; Pandoc converts the same content to HTML, PDF, Word and more. You write the report once..qmd renders to HTML, PDF, Word, slides and more, all by setting format:. The content is authored once.One template, any input
Priya does not want one report. She wants the same report for the Downtown store, then Airport, then Riverside, every week. Rewriting the file six times would reintroduce every error she just removed. The answer is a parameter: a value declared in the YAML header that the document reads, so one template produces many reports.
You add a params: block to the YAML, then refer to it anywhere in the document as params$store. Toggle the widget between Source and Rendered to see the parameter sitting in the header and being used in the body:
Inside the document, params$store is just an ordinary value. Here we set it by hand to show the idea, then use it to compute that store's numbers (Quarto would set it from the header for you):
Now one template can produce a finished report for every store, with no hand-edits, by rendering it once per parameter value:
library(quarto)
# one template -> one finished report per store
for (s in unique(sales$store)) {
quarto_render("weekly-report.qmd",
execute_params = list(store = s),
output_file = paste0("report-", s, ".html"))
}
Make the report for another store
Run the template for the Riverside store. The parameter report_store is already set; complete the filter() so it keeps only the rows where the store column equals the chosen report_store.
Show answer
report_store <- "Riverside"
sales |>
filter(store == report_store) |>
summarise(units = sum(units), revenue = sum(revenue))
#> units revenue
#> 1 180 3600References
A few authoritative places to take this further:
- Quarto: Get Started - install Quarto and render your first document, straight from the Quarto team.
- Quarto: Parameters - the canonical guide to
params:and rendering one template for many inputs. - R Markdown: The Definitive Guide - Xie, Allaire and Grolemund on the chunk-and-YAML model Quarto inherits.
- R for Data Science (2e): Quarto - Wickham, Cetinkaya-Rundel and Grolemund on the reproducible-report workflow.
Lesson 1 complete
You turned a fragile, hand-assembled report into one that updates itself. A Quarto document is a single .qmd with three parts: the YAML header, the prose, and the code chunks. You render it to run the code and produce a finished file. Inline code makes even the sentences reproducible, so the headline and the chart can never drift apart. The same source gives you HTML, PDF or Word by changing one format: line, and a params: block turns that one file into a template that re-runs for any store or any week.
Next, Lesson 2: Telling a story with data. A reproducible report is only useful if a busy reader acts on it. You will learn to lead with the answer, write the executive summary first, and structure a short data story that lands in thirty seconds.