library(tidyverse)
library(knitr)
library(kableExtra)
library(DT)
library(patchwork)Quarto
Learning objectives
- Learn how to generate an html/pdf report using Quarto and RStudio
What is Quarto?
Quarto is an open-source scientific and technical publishing system that provides a means of combining executable R code, code output and textual content in a single document. These documents can then be used to create reports in a variety of different formats, such as PDF, HTML, Word, or even slide decks. Quarto is the next-generation successor to R Markdown, developed by Posit (formerly RStudio). It supports R, Python, Julia and Observable JavaScript out of the box, and the syntax is largely compatible with R Markdown.
This session will provide a brief introduction to Quarto, including how to create a new Quarto document, how to add text and images, how to insert R code chunks, and how to render the document to create a report.
More detailed materials can be found here.
Packages for this session
We will be using the following packages in this session. If you don’t have them installed, you can do so using the install.packages() function.
knitr is the package that Quarto uses (when working with R) to convert your document to various output formats. It is also used to control how the output of R code is rendered in the document, and its kable function is used to create simple tables. Note that you don’t need to load the knitr package explicitly for chunks to run, as it is loaded automatically when you render a Quarto document, but if you want to use the kable function you may wish to load it in order not to have to type knitr::kable() every time.
The kableExtra package extends the functionality of knitr, providing additional functions for formatting tables. The DT package provides a way to create interactive tables in Quarto documents. The patchwork package provides a way to combine multiple ggplots into a single figure.
Creating a Quarto document
We can start a new Quarto document in RStudio from the menu bar:
File –> New File –> Quarto Document...

This will bring up the following dialogue box:

Change the title to something meaningful, add your name as the author if you wish, select the type of document you want Quarto to generate (this can be changed later) and then click Create to create a starter script.
Save the starter script as MyFirstQuarto.qmd. Note the .qmd extension that distinguishes Quarto documents from R Markdown’s .Rmd.
The basic components of a Quarto document
A Quarto file is made up of 3 components:
- Header - metadata and instructions related to rendering the document
- Markdown sections - Text, images, links, tables, lists to be included in the report
- Code chunks - Code chunks to be executed and the output included in the report

You may have noticed that opening a Quarto (.qmd) document caused a few new icons to appear on the toolbar above the script window. For now just click:

The button to convert (or render) the document is now labelled Render (rather than Knit as in R Markdown). Clicking it will convert the document to html format.
In this session we will generate an HTML file, however, it is possible to generate a range of different document types, and these are extensible to link multiple documents into “books” or websites. We’ll keep it simple for this introduction. Let’s look at each section in a little more detail.
Header
The Quarto document starts with a header in YAML format.
The header begins and ends with a line with three hyphens (---). The only required field is the format field, which defines what type of document is to be created. Other fields either define metadata, e.g. author or title, or they contain information related to the rendering of the output document, e.g. whether to include a table of contents or not (we’ll look at this later).
In the example below the title, author, format and date have been specified
---
title: "My First Quarto"
author: "Ashley Sawle"
format: html
date: "2026-04-28"
---
Note that in Quarto we use format: html rather than the R Markdown equivalent output: html_document. Other common formats include pdf, docx and revealjs (for slides).
Markdown sections
Markdown is a markup language that allows you to add formatting to text, such as bold or italics. Unlike in a word processor such as MS Word, the effect of formatting is not visible in a markdown (.md) document, only once the document is rendered to create the output. Markdown uses specific syntax to add formats to the text. The benefit of this is Markdown is lightweight and platform independent.
Quarto combines normal Markdown for text and images with separate chunks that can contain executable R code, the outputs of which can be included in the document.
The full documentation of the Markdown syntax used in Quarto can be found here. Here we will concentrate on the most commonly used elements.
Inline text formatting
Seeing as we have already mentioned bold and italics, let’s see how they work. To apply inline formatting for text, we simply surround the text we want to format with a particular set of symbols. For example to render some text in italics we surround the text with either asterisks or underscores:
This is *italics* or This is _italics_ → This is italics
Other possible inline formatting syntax includes:
Double asterisks/underscores for bold:
This **is bold**orThis __is bold__→ This is boldTilde (
~) for subscript:This is ~subscript~→ This is subscriptCaret (
^) for superscript:This is ^superscript^→ This is superscriptDouble tilde (
~) for strikethrough:~~This is strikethrough~~→This is strikethroughBackticks (
`) for “code” font:This is `code`→ This iscode
Note that any amount of text can come between the two sets of syntax.
Headings
Section headings are created using the # symbol (technically called an octothorp!) at the beginning of the line. The top level is the document title and uses one #:
# Section
Using 2 creates a section header:
## Sub-section → Sub-section
Increasing the number of # symbols creates deeper and deeper levels of sub-sections.
# Section
# Sub-section
## Sub-sub section
### Sub-sub-sub section
#### Sub-sub-sub-sub section
Adding a table of contents
The section headers can be automatically added to a table of contents. As this is “instructions related to rendering the document”, we need to add this information to the header yaml:
format:
html:
toc: true
By default all headings up to level 3 headings are displayed in the table of contents. You can adjust this by specifying toc-depth. With html format, the table of contents defaults to a “floating” position on the right of the document body. You can change its location with toc-location:
format:
html:
toc: true
toc-depth: 4
toc-location: left
Note that Quarto uses hyphens in option names (e.g. toc-depth, toc-location) where R Markdown used underscores (toc_depth, toc_float).
Tab sets
A neat thing to do is to create tab sets. In Quarto, tab sets are created using a fenced div with the class .panel-tabset. Each sub-heading inside the div becomes a tab. For example:
::: {.panel-tabset}
### Bold
Bold is achieved with double asterisks e.g. `**bold**` is rendered as **bold**.
### Italics
Italics is achieved with a single asterisk e.g. `*italics*` is rendered as *italics*.
### Strikethrough
Strikethrough is achieved with double tilde e.g. `~~strikethrough~~` is rendered as
~~Strikethrough~~.
:::
is rendered as:
Bold is achieved with double asterisks e.g. **bold** is rendered as bold.
Italics is achieved with a single asterisk e.g. *italics* is rendered as italics.
Strikethrough is achieved with double tilde e.g. ~~strikethrough~~ is rendered as Strikethrough.
This is a notable difference from R Markdown, which used the {.tabset} attribute on a parent header.
Line breaks
Two consecutive lines of body text in the Quarto document will be read as the same paragraph and concatenated. To insert a line break between two lines either add two (or more) spaces or a backslash at the end of the first line. For example:
This is the first line
There are no spaces after the end of the previous line
is rendered as:
This is the first line There are no spaces after the end of the previous line
whereas:
This is the first line\
There are no spaces after the end of the previous line
is rendered as:
This is the first line
There are no spaces after the end of the previous line
Lists
We can create both unordered lists (bullet points) or ordered lists (numbered).
Unordered lists
To create an unordered list using *, - or + (all do the same thing). You can create nested lists by indenting by 4 spaces.
* Cricket
* Rugby
* Football
* English Premier League
* La Liga
* Serie A
* Basketball
* Volleyball
* Hockey
is rendered as:
- Cricket
- Rugby
- Football
- English Premier League
- La Liga
- Serie A
- Basketball
- Volleyball
- Hockey
Ordered lists
Ordered lists can be created using a number for numeric bullets, a lower case letter for a, b, c…etc., or is for roman numerals. Again indentation can be used to create nested lists. For example
1. Cat
2. Ferret
3. Dog
a. Terriers
i. Jack Russell
ii. Airedale
iii. Yorkshire
iv. West Highland
b. Labradors
c. Spaniels
4. Goldfish
is rendered as:
- Cat
- Ferret
- Dog
- Terriers
- Jack Russell
- Airedale
- Yorkshire
- West Highland
- Labradors
- Spaniels
- Terriers
- Goldfish
It isn’t actually necessary to use particular numbers/letters/roman numerals in any particular order - the correct order for the bullets will be determined when the document is rendered. So in fact the following would result in the same output:
1. Cat
1. Ferret
5. Dog
a. Terriers
i. Jack Russell
i. Airedale
i. Yorkshire
i. West Highland
b. Labradors
a. Spaniels
1. Goldfish
Links
As with a standard html web page, we can add hyperlinks, both to internal sections of the document or to external pages. The general format for creating a link is to surround the link text (what is displayed) with square brackets and then follow this with the link itself (internal tag or external page) surrounded by round brackets:
[This is the text](this_is_the_link)
External links
External links can either be to another html document on the same file system or to a URL elsewhere on the internet.
For example we can link to week 6 documentation, which is in the same folder as this document:
[week 6 document](week6.html) → week 6 document
Alternatively, we can link to pages elsewhere on the internet, e.g:
[The Quarto guide](https://quarto.org/docs/guide/) → The Quarto guide
Internal links to sections
We can link to any section of the current document. By default, Quarto auto-generates an id for each section heading based on the heading text, so you can usually link to a section without adding any tags. For example, the section “Markdown sections” gets the id markdown-sections automatically:
[link to header](#markdown-sections)
You can also assign a custom id to a section by adding a tag to the header. For example:
## Markdown sections {#markdown-header}
Then to link to this section in text we would use:
[link to header](#markdown-header)
e.g. Follow this link to get to the top of this section.
Inserting images
Images can be inserted into the document in a number of ways, but the simplest uses a similar syntax to links, but this time preceded by an exclamation mark:

The link can be a URL to an image elsewhere on the internet or a relative path to an image on the same file system.

inserts the image like this:

This does not give us much control over how the image is rendered. We can control the size by specifying the width in either absolute display pixels or the percentage of the document width with the following syntax:
{width=10%}
inserts the image like this:

{width=150px}
inserts the image like this:

Tables
Most tables to appear in your documents will be data generated by code chunks, however, on rare occasions we may want to manually include a table. This can be achieved using the following syntax.
| Name | Band |
| ----------- | ----------- |
| Mick | Stones |
| John | Beatles |
| Paul | Beatles |
is rendered as:
| Name | Band |
|---|---|
| Mick | Stones |
| John | Beatles |
| Paul | Beatles |
Table alignments can be done using the following syntax:
| Name | Band | Instrument |
| :--- | :----: | ---: |
| John | Beatles | Guitar |
| Paul | Beatles | Bass |
| Keith | Stones | Guitar |
This is rendered as:
| Name | Band | Instrument |
|---|---|---|
| John | Beatles | Guitar |
| Paul | Beatles | Bass |
| Keith | Stones | Guitar |
Blockquotes
A block quote is often used when we want to quote a piece of text from another document. This is done by using the > symbol at the beginning of the line. For example:
> "The R language is a free software environment for statistical
> computing and graphics supported by the R Foundation for Statistical
> Computing. The R language is widely used among statisticians and
> data miners for developing statistical software and data analysis."
> (Wikipedia)
is rendered as:
“The R language is a free software environment for statistical computing and graphics supported by the R Foundation for Statistical Computing. The R language is widely used among statisticians and data miners for developing statistical software and data analysis.” (Wikipedia)
Code blocks
We have seen that we can highlight text as “code” inline using backticks `code`. This is useful for short snippets of code, but if we want to add a longer piece of code as part of the documentation (i.e. not code that we want to run, but just to show the reader), we can use a code block. This is done by surrounding the code with three backticks. For example:
```
metabric %>%
group_by(ER_status, Cancer_type) %>%
summarise(ERBB2_mean = mean(ERBB2)) %>%
top_n(n = 1)
```
This will be rendered as:
metabric %>%
group_by(ER_status, Cancer_type) %>%
summarise(ERBB2_mean = mean(ERBB2)) %>%
top_n(n = 1)
For code that we actually want to run, we will use code chunks.
Code chunks
Code that we want to run during the rendering of the document should be placed in a code chunk. These sections of code are executed when the document is rendered. The results of the code may then be included in the output document. This allows us to dynamically generate tables, figures and other output based on the data and code in the document. This is a powerful feature of Quarto, as it allows us to create reproducible reports that can be easily updated with new data or code changes.
The R code chunk is created by surrounding the code with three backticks and adding {r} after the first three backticks. For example:
```{r}
x <- 10
y <- 20
x + y
```Generates the following in the output:
x <- 10
y <- 20
x + y[1] 30
By default the code is written to a code chunk (we can change this - see below) and any output from the code is written underneath. The output might include anything that would normally be written to the console (such as the result of x + y here), tables, plots, or even warnings or errors.
Creating code chunks
To create a code chunk, you can use the insert icon on the toolbar:

or you can use the keyboard shortcut Ctrl + Alt + I (Windows) or Cmd + Option + I (Mac), or you can type the code chunk manually as shown above. The code chunk will be created at the location of the cursor in the document.
The empty code chunk will look like this:

You’ll notice a few icons on the right in the toolbar above the code chunk. These are used to run the code chunk, run all code chunks above the current chunk, and to manage chunk options (see below).
Running code chunks
To run a code chunk, you can click the green arrow icon in the toolbar above the code chunk, or you can use the keyboard shortcut Ctrl + Shift + Enter (Windows) or Cmd + Shift + Enter (Mac). This will run the code in the chunk and display the output below the chunk.
Chunk options
We can apply a number of options to code chunks to control how they are rendered in the output document.
In Quarto, the recommended way to set chunk options is using the “hash-pipe” syntax (#|) at the start of the chunk. Each option is written on its own line in YAML format:
```{r}
#| echo: false
#| warning: false
x <- 10
y <- 20
x + y
```This is different from R Markdown, where options were written inside the curly braces on the chunk header line, e.g. {r, echo=FALSE, warning=FALSE}. The R-Markdown style still works in Quarto, but the hash-pipe form is preferred because it is easier to read, easier to edit, and works consistently across R, Python and Julia chunks.
Some of the most common options are:
echo: false- do not display the code in the rendered document, but do display the results of the code.include: false- do not display either the code or the results in the document when it is rendered. The code will still run and so any changes it makes to the environment (new objects or changes to existing objects) will be available for subsequent code chunks.message: false- do not display any messages that are generated by the code chunk in the rendered file.warning: false- do not display warnings that are generated by the code chunk in the rendered file.eval: false- do not run the code in the chunk, but display the code in the rendered document.cache: true- cache the results of the code chunk so that it does not need to be re-run every time the document is rendered. This can speed up rendering time for large code chunks or when the code takes a long time to run.fig-widthandfig-height- set the width and height of figures generated by the code chunk. Note the hyphens, where R Markdown used dots (fig.width,fig.height).fig-cap- set the caption for the figure generated by the code chunk. This will be displayed below the figure in the rendered document.
A thorough guide to all the available chunk options can be found here.
Chunk label
We can specify a label for the code chunk by adding it as a label option:
```{r}
#| label: my-chunk
```You can also still write the label directly after r on the chunk header (e.g. {r my-chunk}), as in R Markdown.
This has a number of uses. In RStudio you should see a menu in the bottom left of the script panel:

This gives us a way to navigate through the document and includes any headers and code chunks with labels. This is very useful for long documents.
Document-wide execution options
In R Markdown the convention was to create a “setup” chunk at the start of the document and call knitr::opts_chunk$set() to set defaults for all chunks. In Quarto, the cleaner approach is to use the execute field in the YAML header. For example:
---
title: "My First Quarto"
format: html
execute:
echo: true
warning: false
message: false
---
This sets defaults for the whole document. You can override any of these settings on individual chunks using the hash-pipe syntax.
You can still create a setup chunk to load packages — and that is the recommended place for it:
```{r}
#| label: setup
#| include: false
library(tidyverse)
library(patchwork)
library(knitr)
library(kableExtra)
library(DT)
```A note on the working directory
When evaluating code chunks, the default working directory is the location of the Quarto file. This means that any paths to files you wish to read/write need to be relative to that directory. If you wish to use a different working directory, the easiest approach is to use the here package, or to set the path explicitly at the top of the document.
Tabular output
By default, Quarto will display tables in basically the same way as they would be displayed in the console. For example, if we display the first few rows of the mtcars dataset we get the following:
smallTable <- mtcars %>%
rownames_to_column("car") %>%
select(car, mpg, cyl, wt) %>%
slice(1:5)
smallTable car mpg cyl wt
1 Mazda RX4 21.0 6 2.620
2 Mazda RX4 Wag 21.0 6 2.875
3 Datsun 710 22.8 4 2.320
4 Hornet 4 Drive 21.4 6 3.215
5 Hornet Sportabout 18.7 8 3.440
Basically informative, but not very pretty. There are a lot of things we can do to make the table more functional and look better in our report. The simplest is to use the kable() function from the knitr package.
The kable() function
smallTable %>%
kable()| car | mpg | cyl | wt |
|---|---|---|---|
| Mazda RX4 | 21.0 | 6 | 2.620 |
| Mazda RX4 Wag | 21.0 | 6 | 2.875 |
| Datsun 710 | 22.8 | 4 | 2.320 |
| Hornet 4 Drive | 21.4 | 6 | 3.215 |
| Hornet Sportabout | 18.7 | 8 | 3.440 |
kable generates a simple table using the Markdown syntax that we saw previously. It can be used to control some basic aspects of the appearance of the table, including the number of digits displayed, the alignment of the columns, and the formatting of the table. For example, we can use the digits argument to specify the number of digits to display for each column. We can also use the align argument to specify the alignment of the columns.
smallTable %>%
kable(digits = 2, align = "c")| car | mpg | cyl | wt |
|---|---|---|---|
| Mazda RX4 | 21.0 | 6 | 2.62 |
| Mazda RX4 Wag | 21.0 | 6 | 2.88 |
| Datsun 710 | 22.8 | 4 | 2.32 |
| Hornet 4 Drive | 21.4 | 6 | 3.21 |
| Hornet Sportabout | 18.7 | 8 | 3.44 |
A comprehensive guide to the kable function can be found here.
There are a large number of other packages available to format tables in more sophisticated ways. Here we will look at two packages: kableExtra, which extends the formatting capabilities of kable, and DT, which provides a more interactive table format.
The kableExtra package
The package kableExtra replaces kable() with the function kbl() to display tables. We can then use various formatting commands to control the appearance of the table in much the same way as we add layers to a ggplot. The kableExtra package provides a number of functions that can be used to format tables, including kable_styling(), column_spec(), and row_spec().
smallTable %>%
kbl() %>%
kable_styling(bootstrap_options = c("striped", "hover")) %>%
column_spec(column = 1, bold = TRUE, border_right = TRUE)| car | mpg | cyl | wt |
|---|---|---|---|
| Mazda RX4 | 21.0 | 6 | 2.620 |
| Mazda RX4 Wag | 21.0 | 6 | 2.875 |
| Datsun 710 | 22.8 | 4 | 2.320 |
| Hornet 4 Drive | 21.4 | 6 | 3.215 |
| Hornet Sportabout | 18.7 | 8 | 3.440 |
As well as allowing us to control the formatting of the table ourselves, kableExtra also provides a number of pre-defined styles that we can use to quickly format our tables.
smallTable %>%
kbl() %>%
kable_classic(full_width = F, html_font = "Cambria")| car | mpg | cyl | wt |
|---|---|---|---|
| Mazda RX4 | 21.0 | 6 | 2.620 |
| Mazda RX4 Wag | 21.0 | 6 | 2.875 |
| Datsun 710 | 22.8 | 4 | 2.320 |
| Hornet 4 Drive | 21.4 | 6 | 3.215 |
| Hornet Sportabout | 18.7 | 8 | 3.440 |
Note that it is necessary to the #| html-table-processing: none chunk option. By default, Quarto post-processes HTML tables to apply its own theming, and in doing so it overrides some of the styling that kableExtra adds — including the full_width = FALSE argument used here. If you want this behaviour for every chunk in the document, you can set it once in the YAML header under format: html:.
More details about all the fancy things you can do with kableExtra can be found here.
The DT package
The DT package provides a more interactive table format that allows us to sort, filter, search, and paginate the table. It also provides options to add buttons to export the table to CSV, Excel, or PDF format. The basic command is datatable(), which takes a data.frame as input and returns an interactive table.
longTable <- mtcars %>%
rownames_to_column("car") %>%
select(car, mpg, cyl, wt)
longTable %>%
datatable()There are a lot of options available to control the appearance and functionality of the table. Extensive documentation is available here.
Much of the formatting is done using the options argument, which takes a list of options. The dom option controls the layout of the different elements, and the buttons option controls the buttons that are displayed. The pageLength option controls the number of rows displayed on each page.
The dom option is a string that specifies the layout of the table. The string can contain the following characters:
l- length changing input control (how many rows to display)f- filtering input (search box)t- tablei- table information summary (e.g. “Showing 1 to 10 of 57 entries”)p- pagination control (next/previous buttons)B- buttons (export buttons)r- processing display element (loading indicator)
The order of the characters in the string determines the order in which the elements are displayed.
Let’s add custom column names to the table, remove the search box, change the number of rows displayed on each page, and add a button to export the table to CSV.
By omitting the f character from the dom string, we remove the search box.
To add the export buttons, we need to add the buttons option to the options argument, but we also need to add the B character to the dom string and instruct the table to use the “Buttons” extension.
longTable %>%
datatable(
extensions = "Buttons",
options = list(
dom = "Btip",
buttons = c("csv", "excel"),
pageLength = 5),
colnames = c("Car", "Miles per gallon", "Cylinders", "Weight")
)The DT R package is a wrapper for the JavaScript library DataTables. Be careful when searching the web for information about DT that you are not looking at the JavaScript documentation. Also, be careful not to confuse the DT package with the data.table package, which is a different package for fast data manipulation in R.
NOTE: Be wary of creating very large tables in Quarto documents. The data in the table is all embedded in the final document when it is rendered. If you have a very large table the resulting document can be very large.
Plots
If a code chunk generates a plot, the plot will be displayed in the output document.
```{r}
#| label: plot
mtcars %>%
ggplot(aes(x = mpg, y = wt)) +
geom_point() +
labs(title = "Scatter plot of weight vs miles per gallon",
x = "Miles per gallon",
y = "Weight") +
theme_minimal()
```is rendered as:

Using chunk options we can control the size of the plot in the document and add a caption to the plot.
The default size of the plot is 7 inches wide and 5 inches high. We can change the size of the plot using the fig-width and fig-height options.
Note that the caption can be specified directly with fig-cap. In Quarto, chunk option values are written in YAML, so for a string value you can simply quote it.
```{r}
#| label: plot2
#| fig-width: 5
#| fig-height: 3
#| fig-cap: "Scatter plot of weight vs miles per gallon"
mtcars %>%
ggplot(aes(x = mpg, y = wt)) +
geom_point() +
labs(x = "Miles per gallon",
y = "Weight") +
theme_minimal()
```is rendered as:

The patchwork package
It is often the case that we want to put multiple plots together in a single figure. There are various packages that can be used to do this such as ggarrange, gridExtra, and cowplot. Here we will look at the patchwork package, which provides a very simple and intuitive way to combine ggplots in a grid.
First create each plot and rather than printing them, assign them to a variable. Then we can use the patchwork syntax to combine the plots.
p1 <- mtcars %>%
mutate(across(cyl, factor)) %>%
ggplot(aes(x = mpg, y = wt)) +
geom_point(aes(colour = cyl)) +
geom_text(label = "A", x = 22.5, y = 3.5, size = 50)
p2 <- mtcars %>%
mutate(across(cyl, factor)) %>%
ggplot(aes(x = gear, y = hp)) +
geom_point(aes(colour = cyl)) +
geom_text(label = "B", x = 4, y = 195, size = 50)
p1 + p2
patchwork provides a lot of options for combining plots, including + to add plots together, / to stack plots vertically, and | to stack plots horizontally. We can use plot_layout() to control various aspects of the layout, for example we can combine legends when they are the same. We can also use plot_annotation() to add a title and subtitle to the figure (and other annotations).
I am going to reuse the same plots a few times just to show you how the layout works.
((p1 + p2) / (p2 + p1 + p2) | (p1 / p2 / p1)) +
plot_layout(guides = "collect") +
plot_annotation(title = "Patchwork example",
subtitle = "Combining plots with patchwork")
Here I have gathered plots into three plot groups - p1 + p2, p2 + p1 + p1, and p1 / p2 / p1. In the final group I have used the / operator to stack the plots vertically. I have then stacked the first two groups above each other and the third group to the right using the | operator.
The plot_layout() and plot_annotation() can be added to any grouping level so to get them to apply to the whole figure, we put all three groups in brackets to define the whole figure. It can take a bit of getting used to, but once you get the hang of it, it is very simple to create complex figures with many plots.
Extensive documentation is available here.
Inline R code
It is also possible to include R code inline in the markdown. This is done by surrounding the code with single backticks and starting it with r. This is useful if, for example, you want to include a value from a variable in the text. For example:
```{r}
#| label: inline
six_cyl_mean_mpg <- mtcars %>%
filter(cyl == 6) %>%
summarise(mpg = mean(mpg)) %>%
pull(mpg)
```followed by the prose line:
The mean mpg of cars with 6 cylinders was **`r six_cyl_mean_mpg`**.
Will be rendered as:
six_cyl_mean_mpg <- mtcars %>%
filter(cyl == 6) %>%
summarise(mpg = mean(mpg)) %>%
pull(mpg)The mean mpg of cars with 6 cylinders was 19.7428571.
Quarto vs R Markdown — quick reference
If you have used R Markdown before, here are the main differences to keep in mind:
| R Markdown | Quarto |
|---|---|
.Rmd file extension |
.qmd file extension |
output: html_document |
format: html |
toc_float: true |
toc-location: left (or right) |
Underscores in options (toc_depth) |
Hyphens in options (toc-depth) |
| Knit button | Render button |
{r, echo=FALSE} chunk header |
#| echo: false hash-pipe option |
knitr::opts_chunk$set(...) |
YAML execute: block |
### Headers {.tabset} |
::: {.panel-tabset} div |
fig.width, fig.cap |
fig-width, fig-cap |
The R Markdown forms still mostly work in Quarto for backward compatibility, but the Quarto forms above are preferred for new documents.
Challenge
Based on the information in this document and in the various links, create a report to match the one here.
I have hidden the code except for the chunk loading the data and the last chunk, which prints the session info. Where the code chunks should be you’ll see:
Code chunk: *some details*
Replace these as necessary with your own code - you may want to refer back to previous sessions.
You may also need to do a bit of searching in function help pages, documentation linked above or on the web generally to figure out some of the code. For example, in the final figure I have added sub-figure labels (a, b, c, d) using patchwork. I couldn’t remember how to do this, so I did a web search for “patchwork figure labels”.
Don’t worry about the grey banner at the top, that is part of this website.
Acknowledgements
This session was developed with reference to materials by Alexia Cardona and the Data Carpentry project, and the official Quarto documentation.
Session details
It is good practice to include details of the R environment used in the analysis, including the R version, packages used and their version numbers. This can be done at the end of the report. The neatest way to do this is to use the devtools package.
devtools::session_info()─ Session info ───────────────────────────────────────────────────────────────
setting value
version R version 4.5.3 (2026-03-11)
os Ubuntu 24.04.4 LTS
system x86_64, linux-gnu
ui X11
language (EN)
collate en_US.UTF-8
ctype en_US.UTF-8
tz Europe/London
date 2026-04-28
pandoc 3.8.3 @ /usr/lib/rstudio/resources/app/bin/quarto/bin/tools/x86_64/ (via rmarkdown)
quarto 1.8.24 @ /usr/local/bin/quarto
─ Packages ───────────────────────────────────────────────────────────────────
package * version date (UTC) lib source
bslib 0.10.0 2026-01-26 [1] CRAN (R 4.5.2)
cachem 1.1.0 2024-05-16 [1] CRAN (R 4.5.0)
cli 3.6.5 2025-04-23 [1] CRAN (R 4.5.0)
crosstalk 1.2.2 2025-08-26 [1] CRAN (R 4.5.1)
devtools 2.4.6 2025-10-03 [1] CRAN (R 4.5.1)
digest 0.6.39 2025-11-19 [1] CRAN (R 4.5.2)
dplyr * 1.2.0 2026-02-03 [1] CRAN (R 4.5.2)
DT * 0.34.0 2025-09-02 [1] CRAN (R 4.5.1)
ellipsis 0.3.2 2021-04-29 [1] CRAN (R 4.5.0)
evaluate 1.0.5 2025-08-27 [1] CRAN (R 4.5.1)
farver 2.1.2 2024-05-13 [1] CRAN (R 4.5.0)
fastmap 1.2.0 2024-05-15 [1] CRAN (R 4.5.0)
forcats * 1.0.1 2025-09-25 [1] CRAN (R 4.5.1)
fs 1.6.6 2025-04-12 [1] CRAN (R 4.5.0)
generics 0.1.4 2025-05-09 [1] CRAN (R 4.5.0)
ggplot2 * 4.0.2 2026-02-03 [1] CRAN (R 4.5.2)
glue 1.8.0 2024-09-30 [1] CRAN (R 4.5.0)
gtable 0.3.6 2024-10-25 [1] CRAN (R 4.5.0)
hms 1.1.4 2025-10-17 [1] CRAN (R 4.5.1)
htmltools 0.5.9 2025-12-04 [1] CRAN (R 4.5.2)
htmlwidgets 1.6.4 2023-12-06 [1] CRAN (R 4.5.0)
jquerylib 0.1.4 2021-04-26 [1] CRAN (R 4.5.0)
jsonlite 2.0.0 2025-03-27 [1] CRAN (R 4.5.0)
kableExtra * 1.4.0 2024-01-24 [1] CRAN (R 4.5.0)
knitr * 1.51 2025-12-20 [1] CRAN (R 4.5.2)
labeling 0.4.3 2023-08-29 [1] CRAN (R 4.5.0)
lifecycle 1.0.5 2026-01-08 [1] CRAN (R 4.5.2)
lubridate * 1.9.5 2026-02-04 [1] CRAN (R 4.5.2)
magrittr 2.0.4 2025-09-12 [1] CRAN (R 4.5.1)
memoise 2.0.1 2021-11-26 [1] CRAN (R 4.5.0)
otel 0.2.0 2025-08-29 [1] CRAN (R 4.5.1)
patchwork * 1.3.2 2025-08-25 [1] CRAN (R 4.5.1)
pillar 1.11.1 2025-09-17 [1] CRAN (R 4.5.1)
pkgbuild 1.4.8 2025-05-26 [1] CRAN (R 4.5.0)
pkgconfig 2.0.3 2019-09-22 [1] CRAN (R 4.5.0)
pkgload 1.5.0 2026-02-03 [1] CRAN (R 4.5.2)
purrr * 1.2.1 2026-01-09 [1] CRAN (R 4.5.2)
R6 2.6.1 2025-02-15 [1] CRAN (R 4.5.0)
RColorBrewer 1.1-3 2022-04-03 [1] CRAN (R 4.5.0)
readr * 2.1.6 2025-11-14 [1] CRAN (R 4.5.2)
remotes 2.5.0 2024-03-17 [1] CRAN (R 4.5.0)
rlang 1.1.7 2026-01-09 [1] CRAN (R 4.5.2)
rmarkdown 2.30 2025-09-28 [1] CRAN (R 4.5.1)
rstudioapi 0.18.0 2026-01-16 [1] CRAN (R 4.5.2)
S7 0.2.1 2025-11-14 [1] CRAN (R 4.5.2)
sass 0.4.10 2025-04-11 [1] CRAN (R 4.5.0)
scales 1.4.0 2025-04-24 [1] CRAN (R 4.5.0)
sessioninfo 1.2.3 2025-02-05 [1] CRAN (R 4.5.0)
stringi 1.8.7 2025-03-27 [1] CRAN (R 4.5.0)
stringr * 1.6.0 2025-11-04 [1] CRAN (R 4.5.2)
svglite 2.2.2 2025-10-21 [1] CRAN (R 4.5.2)
systemfonts 1.3.1 2025-10-01 [1] CRAN (R 4.5.1)
textshaping 1.0.4 2025-10-10 [1] CRAN (R 4.5.1)
tibble * 3.3.1 2026-01-11 [1] CRAN (R 4.5.2)
tidyr * 1.3.2 2025-12-19 [1] CRAN (R 4.5.2)
tidyselect 1.2.1 2024-03-11 [1] CRAN (R 4.5.0)
tidyverse * 2.0.0 2023-02-22 [1] CRAN (R 4.5.1)
timechange 0.4.0 2026-01-29 [1] CRAN (R 4.5.2)
tzdb 0.5.0 2025-03-15 [1] CRAN (R 4.5.0)
usethis 3.2.1 2025-09-06 [1] CRAN (R 4.5.1)
vctrs 0.7.1 2026-01-23 [1] CRAN (R 4.5.2)
viridisLite 0.4.3 2026-02-04 [1] CRAN (R 4.5.2)
withr 3.0.2 2024-10-28 [1] CRAN (R 4.5.0)
xfun 0.56 2026-01-18 [1] CRAN (R 4.5.2)
xml2 1.5.2 2026-01-17 [1] CRAN (R 4.5.2)
yaml 2.3.12 2025-12-10 [1] CRAN (R 4.5.2)
[1] /home/sawle01/R/x86_64-pc-linux-gnu-library/4.5
[2] /usr/local/lib/R/site-library
[3] /usr/lib/R/site-library
[4] /usr/lib/R/library
* ── Packages attached to the search path.
──────────────────────────────────────────────────────────────────────────────