We’ve been preparing for an upcoming workshop by building our first presentation with Quarto and Revealjs. Here’s what we’ve learned so far.
This spring, it seemed like everyone in the R community was suddenly talking about Quarto, the new multi-language successor to RMarkdown.
Over the weekend, I wrote up my notes about using and teaching Quarto, based on my experiences working with the development team for over a year.
— Alison Presmanes Hill (@apreshill) April 5, 2022
I think (hope?) it is safe to talk about it now 😆https://t.co/qg98fEsW7g
Here at IPUMS PMA, we’ve been happy RMarkdown users for several years. After all, our blog is built entirely with Distill for RMarkdown - this allows readers to download every post as a fully executable R script right from our GitHub page. Internally, we use RMarkdown for all kinds of everyday tasks like:
StataSE-64.exe
Fortunately, because Quarto and RMarkdown both use Knitr, it’s easy to upgrade! Almost everything we’ve ever made with RMarkdown can be rendered by Quarto (except for some changes to YAML fields in the header).
One notable exception: we’ve previously used the popular Xaringan R package to create slide presentations with RMarkdown. Because Quarto is entirely built on Pandoc, we figured it’s high time to adopt a Pandoc-defined output format, instead. Below is our first attempt at using Revealjs in Quarto!
If you’ve ever built slides in RMarkdown before, the basics you’ll need to get started with RevealJS in Quarto will be very familiar. First, we downloaded Quarto and created a new RStudio project containing a file called slides.qmd
. We also created a few subfolders:
data
includes the toy datasets featured in our workshopimages
includes any image that appears on a slide (including gifs
and png
files)slides_files
is created automatically when slides.qmd
is renderedThe slides.qmd
file looks very much like a standard RMarkdown file divided by several headings, each representing a new slide. Title slides for major sections can be created with a level-1 heading (#
) like this:
# 1 - IPUMS PMA DATA
Within sections, we built individual slides with titles set by level-2 headings (##
) like this:
## Mapping Birth Outcomes by EA
```{r, fig.height=4, fig.align='center'}
ggplot() +
layer_spatial(ea_summary_gps, aes(fill = many_births)) +
layer_spatial(shape, alpha = 0) +
theme_minimal() ```
As you can see above, we’ve incorporated the same fonts that appear on our blog and across all IPUMS websites. These are applied in a custom.scss
file in the root folder for our project. We’re certainly not experts at CSS, but this file was easy to build because Quarto provides great documentation for pre-defined Sass Variables. Our custom.scss
file looks like this:
/*-- scss:defaults --*/
: cabrito_sans_norm_regular;
$font-family-sans-serif: cabrito_sans_norm_regular;
$presentation-heading-font: #00263A;
$presentation-heading-color: uppercase;
$presentation-heading-text-transform: 500;
$presentation-heading-font-weight: #98579B;
$link-color: left;
$presentation-title-slide-text-align: 0.6em;
$code-block-font-size: .8; $presentation-font-smaller
Sass Variable | What it does |
---|---|
$font-family-sans-serif | Sets main serif font |
$presentation-heading-font | Sets font for headings |
$presentation-heading-color | Sets color for headings (Navy) |
$presentation-heading-text-transform | All headings to uppercase |
$presentation-heading-font-weight | Lighter font weight |
$link-color | Sets color for links (Pink) |
$presentation-title-slide-text-align | Title slides left aligned |
$code-block-font-size | Slightly smaller code font |
$presentation-font-smaller | Proportional adjustment for all fonts |
Addtionally, we specified a few global settings in the YAML header of the slides.qmd
file.
format:
revealjs:
theme: [default, custom.scss]
logo: images/logo-navy.png
chalkboard: true
smaller: true
scrollable: false
incremental: true
preview-links: true
YAML option | What it does |
---|---|
theme | Use the default Bootstrap 5 theme, except where our custom.scss file says otherwise |
logo | Path the the IPUMS PMA logo image (inserted in the bottom-right of each slide) |
chalkboard | Enables drawing on slides (see button at bottom-left) |
smaller | Proportional size adjustment for all fonts (set in custom.scss ) |
scrollable | Disable scrolling: we wanted to adjust figure sizes manually so that everything fits on the page |
incremental | Display bullets and content in fragment tags incrementally (on click) |
preview-links | Open external links in a preview window |
One thing that took practice: creating multiple columns with fenced div containers! A typical multi-column slides looks something like this:
## Downloading IPUMS PMA data {.center .nonincremental}
::: {.columns}
:::: {.column width="50%"}
![](images/pma/home.png){}
::::
:::: {.column width="50%"}
[Visit the IPUMS PMA data website](https://pma.ipums.org/pma/)
* Sample
* Burkina Faso
* Longitudinal
* Female Respondents Only
* Variables
* [RESULTFQ](https://pma.ipums.org/pma-action/variables/RESULTFQ)
* [PANELBIRTH](https://pma.ipums.org/pma-action/variables/PANELBIRTH)
* [PANELWEIGHT](https://pma.ipums.org/pma-action/variables/PANELWEIGHT)
* [EAID](https://pma.ipums.org/pma-action/variables/EAID)
* [URBAN](https://pma.ipums.org/pma-action/variables/URBAN)
:::: :::
This works great, but things can get complicated quickly. In this slide, we wanted to show several sentences incrementally on the left column, but we didn’t want to waste space with bullets. Instead, we inserted .fragment
tags around the text we wanted to highlight in each step. Then, we added the option .fade-in-then-semi-out
to fade the color of each point once we’d moved on the the next one.
## About PMA GPS data {auto-animate="true"}
::: {.columns}
:::: {.column width="60%"}
::::: {.fragment .fade-in-then-semi-out}
PMA uses spatially referenced sample clusters - called "enumeration areas" (EAs) - sampled by probability proportional to population size.
:::::
::::: {.fragment .fade-in-then-semi-out}
At the beginning of the panel study, 35 households were randomly selected within each EA.
:::::
::::
:::: {.column width="40%"}
:::: :::
After the first two sentences, we wanted to show a figure in the right column representing a PMA sample cluster before moving on to the next two sentences. The easiest way we found to do this was to create a duplicate slide where the first two sentences were faded right away. It took quite a bit of trial-and-error to get the size and .absolute
position of our figure just the way we wanted!
## About PMA GPS data {auto-animate="true" visibility="uncounted"}
::: {.columns}
:::: {.column width="60%"}
::::: {style="opacity:0.5"}
PMA uses spatially referenced sample clusters - called "enumeration areas" (EAs) - sampled by probability proportional to population size.
At the beginning of the panel study, 35 households were randomly selected within each EA.
:::::
::::: {.fragment .fade-in-then-semi-out}
IPUMS PMA does not disseminate the GPS coordinates for EAs, but you may [apply here](https://www.pmadata.org/data/request-access-datasets) for access directly from PMA.
:::::
::::: {.fragment .fade-in-then-semi-out}
Today, we'll be using **falsified** GPS coordinates as an example.
:::::
::::
:::: {.column width="40%"}
![](images/pma/gps1.png){.absolute top=100 right=50 height=300}
:::: :::
Next, we wanted to demonstrate that we’d be using falsified locations for sample clusters in the workshop. In short, we’d created a toy version of the GPS data researchers can obtain from PMA, whereby we jittered each point in a random direction by a random distance within a preset range. To illustrate, we used the RevealJS auto-animate feature to drag the position of our figure across the slide. This required a second duplicate slide with a new .absolute
position for our figure.
## About PMA GPS data {auto-animate="true" visibility="uncounted"}
::: {.columns}
:::: {.column width="60%"}
::::: {style="opacity:0.5"}
PMA uses spatially referenced sample clusters - called "enumeration areas" (EAs) - sampled by probability proportional to population size.
At the beginning of the panel study, 35 households were randomly selected within each EA.
IPUMS PMA does not disseminate the GPS coordinates for EAs, but you may [apply here](https://www.pmadata.org/data/request-access-datasets) for access directly from PMA.
:::::
Today, we'll be using **falsified** GPS coordinates as an example.
::::
:::: {.column width="40%"}
![](images/pma/gps1.png){.absolute top=300 right=0 height=300}
:::: :::
Finally, we wanted to emphasize that our data only provide the centroid of a randomly displaced sample cluster, not the location of any household within the cluster. We added one more duplicate slide, except that it shows a modified figure with a red +
sign in the middle.
## About PMA GPS data {auto-animate="true" visibility="uncounted"}
::: {.columns}
:::: {.column width="60%"}
::::: {style="opacity:0.5"}
PMA uses spatially referenced sample clusters - called "enumeration areas" (EAs) - sampled by probability proportional to population size.
At the beginning of the panel study, 35 households were randomly selected within each EA.
IPUMS PMA does not disseminate the GPS coordinates for EAs, but you may [apply here](https://www.pmadata.org/data/request-access-datasets) for access directly from PMA.
Today, we'll be using **falsified** GPS coordinates as an example.
:::::
The coordinates represent the <span style="color:red">**centroid**</span> of an enumeration area, *not* the location of any sampled household.
::::
:::: {.column width="40%"}
![](images/pma/gps2.png){.absolute top=300 right=0 height=300}
:::: :::
The result looks like this:
You can also use animation together with line highlighting to incrementally build complex coding examples. Here, we use three copies of the same slide to show how we summarise births by enumeration area, and then divide all enumeration areas into upper and lower halves.
In each duplicate slide, we use code-line-numbers
to specify highlighting for a different line in the subsequent code chunk.
## Birth outcomes by EA {auto-animate=true}
::: {.fragment .fade-in}
Where are the enumeration areas where more women gave birth than average?
:::
::: {.fragment .fade-in}
```{r}
ea_summary <- pma %>%
as_survey_design(weight = PANELWEIGHT) %>%
group_by(ea = EAID_1, urban = URBAN == 1) %>%
summarise(birth_prop = survey_mean(PANELBIRTH_2 == 1, vartype = NULL)) %>%
ungroup()
```
:::
::: {.fragment .fade-in}
```{r, echo=FALSE}
ea_summary
```
:::
## Birth outcomes by EA {auto-animate="true" visibility="uncounted"}
Where are the enumeration areas where more women gave birth than average?
```{r, `code-line-numbers` = "6-8"}
ea_summary <- pma %>%
as_survey_design(weight = PANELWEIGHT) %>%
group_by(ea = EAID_1, urban = URBAN == 1) %>%
summarise(birth_prop = survey_mean(PANELBIRTH_2 == 1, vartype = NULL)) %>%
ungroup() %>%
mutate(
ntile = ntile(birth_prop, 2)
)
```
```{r, echo=FALSE}
ea_summary
```
## Birth outcomes by EA {auto-animate="true" visibility="uncounted"}
Where are the enumeration areas where more women gave birth than average?
```{r, `code-line-numbers` = "8"}
ea_summary <- pma %>%
as_survey_design(weight = PANELWEIGHT) %>%
group_by(ea = EAID_1, urban = URBAN == 1) %>%
summarise(birth_prop = survey_mean(PANELBIRTH_2 == 1, vartype = NULL)) %>%
ungroup() %>%
mutate(
ntile = ntile(birth_prop, 2),
many_births = ntile == 2
)
```
```{r, echo=FALSE}
ea_summary ```
Needless to say, we’ve very excited about Revealjs and all of the other new features made possible by Quarto! At the same time, we have a lot to learn (particularly around interactivity and custom styling). If you, too, are experimenting with your first Quarto project, we’d recommend any of these great resources to help get started:
If you see mistakes or want to suggest changes, please create an issue on the source repository.