print('Hello Quarto!')
[1] "Hello Quarto!"
Use the Quarto document preparation system to create dynamic documents that combine text and code. Learn how to share these documents with colleagues.
quarto
Ensure you have the quarto
R package installed. Look in RStudio’s Packages pane and install if not found when searching for “quarto”.
Additionally, you can install the Quarto Command Line Interface (CLI). This will allow you to run Quarto from the command line and includes additional features not included with the R package. See the quarto setup section for more info.
Quarto is a relatively new document preparation system that lets you create reproducible and dynamic content that is easily shared with others. Quarto is integrated with RStudio and allows you to combine plain text language with analysis code in the same document.
Quarto belongs to a class of literate programming tools called dynamic documents (Knuth 1984). It is not the first of its kind, but it builds substantially on its predecessors by bridging multiple programming langues.
Advantages of creating analyses using Quarto include:
This next section will run through the very basics of creating a Quarto document, some of the options for formatting, and how to generate shared content. You’ll follow along in this module.
Create a new project in RStudio, first open RStudio and select “New project” from the File menu at the top.
Then select “New Directory”. Create a directory in a location that’s easy to find.
Open a new Quarto file from the File menu under New file > Quarto Document.
Enter a title for the document (e.g., “Quarto practice”) and your name as the author. Use the defaults for the other options and hit “Create”.
Save the file in the project root directory (give it any name you want).
Let’s get familiar with the components of a Quarto document.
The three main components of a Quarto document are:
The new file includes some template material showing the main components of a Quarto document. The content at the top is called YAML, which defines global options for the document.
---
title: "Quarto practice"
author: "Marcus Beck"
editor: visual
---
You’ll also notice that there’s a button on the top-left that lets you toggle between “source” or “visual” editor mode. The source editor simply lets you add text to the document, whereas the visual editor lets you add content that is partially rendered. First time Quarto users may prefer the visual editor.
Using the visual editor, we can insert a code chunk (or code cell). This can be done by selecting the appropriate option from the Insert menu. Note the variety of programming langues that can be used with the code chunk.
We can enter any code we want in the code chunks, including options for how the code chunk is evaluated. Options are specified using the hashpipe notation, #|
.
```{r}
#| echo: true
print('Hello Quarto!')
```
When the file is rendered, the code is run and results displayed in the output. There are many options to change how code chunks are executed, which we’ll discuss below.
print('Hello Quarto!')
[1] "Hello Quarto!"
We can also run the code chunks separately without rendering the file using the arrow buttons on the top right in the source document. This can be useful for quickly evaluating your code as you include it in the file.
Code chunks are executed in the order they appear in the document when a .qmd file is rendered.
Descriptive text can be entered anywhere else in the file. This is where we can describe in plain language what our analysis does or any other relevant information. Text can be entered as-is or using simple markdown text that can format the appearance of the output. If you’re using the visual editor, you can use some of the items in the file menu to modify the text appearance. In the source editor, you can manually enter markdown text:
I can write anything I want right here. Here's some **bold text**.
I can also make lists
1. Item 1
1. Item 2
When the file is rendered, the markdown text will be formatted. The text will already be formatted if you’re using the visual editor:
I can write anything I want right here. Here’s some bold text.
I can also make lists
Render the .qmd file to the output format.
The source file is a .qmd document. We need to render the document to create the output format - HTML (default), PDF, or Word. The following happens when you hit the render button at the top.
Here’s what your RStudio session should look like (note the three parts of the source .qmd document - YAML, code chunk, and Markdown text). The rendered HTML file will appear in the Viewer pane on the right.
A rendered Quarto document as an HTML, PDF, Word, or other file format is stand-alone and can be shared with anybody!
The behavior of the code chunks when the file is rendered can be changed using the many options available in Quarto. This can be useful for a few reasons.
Code chunk options can be applied globally to all chunks in the document or separately for each chunk.
To apply them globally, they’ll look something like this in the YAML, where options are added after execute:
---
title: "My Document"
execute:
echo: false
warning: false
---
Be careful with indentation in the YAML, the document won’t render if the indentation is incorrect.
To apply to individual code chunks, use the #|
(hashpipe) notation at the top of the code chunk. This will override any global options if you’ve included them in the top YAML. Below, echo: true
indicates that the code will be displayed in the rendered output.
```{r}
#| echo: true
plot(1:10)
```
Here’s a short list of other useful execution options:
Option | Description |
---|---|
eval |
Evaluate the code chunk (if false , just echos the code into the output). |
echo |
Include the source code in output |
output |
Include the results of executing the code in the output (true , false , or asis to indicate that the output is raw markdown and should not have any of Quarto’s standard enclosing markdown). |
warning |
Include warnings in the output. |
error |
Include errors in the output (note that this implies that errors executing code will not halt processing of the document). |
include |
Catch all for preventing any output (code or results) from being included (e.g. include: false suppresses all output from the code block). |
message |
Include messages in rendered output |
R code can also be executed “inline” outside of code chunks. This can be useful if you want to include statements that reference particular values or information that is linked directly to data. Inline R code is entered using the r
syntax followed by code.
I can enter inline text like `r 1 + 1`.
Text with inline R code will look like this when the document is rendered.
I can enter inline text like 2.
Figures and tables are easily added in Quarto, created using R code or importing from an external source.
Any figures created in code chunks will be included in the rendered output. Some relevant code chunk options for figures include fig-height
, fig-width
, fig-cap
, label
(for cross-referencing) and fig-align
.
```{r}
#| label: fig-myhist
#| fig-height: 4
#| fig-width: 6
#| fig-cap: "Here's my awesome histogram."
#| fig-align: "center"
<- rnorm(100)
vals hist(vals)
```
<- rnorm(100)
vals hist(vals)
Figures can be cross-referenced in the text using the @
notation with the figure label.
Here's a cross-reference to @fig-myhist.
When the file is rendered, the appropriate figure number will be displayed with a link to the figure:
Here’s a cross-reference to Figure 2.1.
Similarly, tabular output can be created inside code chunks.
```{r}
#| label: tbl-mytable
#| tbl-cap: "Here's my awesome table."
<- data.frame(
totab Species = c('Oysters', 'Seagrass', 'Sand'),
Count = c(12, 5, 4)
)::kable(totab)
knitr```
<- data.frame(
totab Species = c('Oysters', 'Seagrass', 'Sand'),
Count = c(12, 5, 4)
)::kable(totab) knitr
Species | Count |
---|---|
Oysters | 12 |
Seagrass | 5 |
Sand | 4 |
And a cross-reference:
Here's a cross-reference to @tbl-mytable.
Here’s a cross-reference to Table 2.1.
Label tags for tables and figures must include the tbl-
or fig-
prefix for proper cross-referencing.
Figures can also be imported from an external source (e.g., from your computer or the web) using the ![]()
notation. You can also simply add a figure from the file menu using the Visual editor.
![](figs/quarto/oysters.jpg)
You can also add a figure from a URL using the same notation.
![](https://unsplash.com/photos/HH-MuVCKal0)
Adding captions and labels to external figures looks something like this:
![Here are some beautiful oysters.](figs/quarto/oysters.jpg){#fig-oysters}
The cross-reference is done the same.
's a cross-reference to @fig-oysters Here
Here's a cross-reference to Figure 2.2.
Likewise, tables can be imported from an external source (e.g., Excel). You’ll want to do this in a code chunk and add the appropriate options (e.g., to cross-reference Table 2.2).
```{r}
#| label: tbl-habitats
#| tbl-cap: "The first six rows of our tidy data"
<- readxl::read_excel('data/tidy.xlsx')[1:6, ]
mytab ::kable(mytab)
knitr```
<- readxl::read_excel('data/tidy.xlsx')[1:6, ]
mytab ::kable(mytab) knitr
Location | Habitat | Year | Acres | Category |
---|---|---|---|---|
Clear Bay | Seagrass | 2019 | 519 | B |
Clear Bay | Oysters | 2019 | 390 | B |
Clear Bay | Sand | 2019 | 742 | C |
Fish Bay | Seagrass | 2019 | 930 | B |
Fish Bay | Oysters | 2019 | 680 | A |
Fish Bay | Sand | 2019 | 611 | A |
Visit these links for full details on figures and tables in Quarto. R also has a rich library of packages for producing tables, most of which play nice with Quarto.
htmlwidgets
The htmlwidgets
package allows you to embed dynamic components directly into a Quarto HTML page. There are several packages that use htmlwidgets
to automatically embed the required JavaScript visualization libraries. This does not require any knowledge of JavaScript, nor use of a Shiny Server.
leaflet
The leaflet
package can be used to create interactive maps (also see mapview
for an “out-of-the-box” option). Here’s a quick map of where we are - click on the marker to view the popup.
library(leaflet)
leaflet() %>%
addTiles() %>% # Add default basemap tiles
addMarkers(lng = -122.663, lat = 45.529, popup = "CERF 2023 conference")
plotly
and dygraphs
The plotly
and dygraphs
packages allow you to create interactive plots. They provide similar functionality, but serve different purposes.
library(plotly)
library(tibble)
# data to plot
<- tibble(
toplo Species = c('Oysters', 'Seagrass', 'Sand'),
`Clear Bay` = c(12, 5, 4),
`Fish Bay` = c(6, 7, 9)
)
# make a plotly plot
<- plot_ly(toplo, x = ~Species, y = ~`Clear Bay`, type = 'bar', name = 'Clear Bay')
fig <- fig %>% add_trace(y = ~`Fish Bay`, name = 'Fish Bay')
fig <- fig %>% layout(yaxis = list(title = 'Count'), barmode = 'group')
fig
fig
The plotly
package has an additional feature that can easily transform existing ggplot
objects into plotly
objects using the ggplotly()
function. This works fairly well for simple plots, although it is usually a better option to build plotly
plots from scratch.
library(ggplot2)
library(tidyr)
# data to plot
<- tibble(
toplo Species = c('Oysters', 'Seagrass', 'Sand'),
`Clear Bay` = c(12, 5, 4),
`Fish Bay` = c(6, 7, 9)
%>%
) pivot_longer(-Species, names_to = 'Bay', values_to = 'Count')
# make a ggplot
<- ggplot(toplo, aes(x = Species, y = Count, fill = Bay)) +
fig geom_bar(stat = 'identity', position = 'dodge')
# conver to plotly
ggplotly(fig)
Plotly
also works well for three-dimensional plotting. Here we show a bathymetric map of Tampa Bay. The input file is a raster object converted to a matrix (see here)
library(plotly)
# file created from a DEM, see
load(file = 'data/demmat.RData')
plot_ly(z = ~demmat) %>%
add_surface(colorbar = list(title = 'Depth (m)'))
We can change some of the options using the layout()
function. The aspect ratio, grid lines, and axis labels are all changed by created a list()
object to pass to layout()
. The color is changed in the add_surface()
function (options here).
# setup plot options
<- list(showgrid = F, title = '',
axopt zerolinecolor='rgb(255, 255, 255)',
tickvals = NA)
<- list(
scene aspectmode = 'manual',
aspectratio = list(x = 0.7, y = 1, z = 0.1),
xaxis = axopt, yaxis = axopt, zaxis = axopt
)
# create plot
plot_ly(z = ~demmat) %>%
add_surface(colorbar = list(title = 'Depth (m)'), colorscale = 'Jet',
reversescale = T) %>%
layout(scene = scene)
The dygraphs
package is designed for time series data. First, we create a time series with random data, then plot it with dygraphs
with a range selector.
library(dygraphs)
# create data
<- 1000
n <- cumsum(rnorm(n))
y <- seq.Date(Sys.Date(), by = 'day', length.out = n)
dts <- tibble(
toplo Date = dts,
y = y
)
dygraph(toplo) %>%
dyRangeSelector()
crosstalk
The crosstalk
package can incorporate additional dynamic functionality in a Quarto document. As the name implies, it allows linking between plots and tables by including embedded Javascript in the rendered HTML file. This allows functionality that looks interactive as in a Shiny application, but does not require Shiny Server.
library(crosstalk)
library(leaflet)
library(DT)
library(dplyr)
# import water quality data
<- read.csv('https://github.com/tbep-tech/shiny-workshop/raw/main/data/tbwqdat.csv') %>%
tbwqdat filter(mo == 7)
# create shared data
<- SharedData$new(tbwqdat)
sd
# create a filter input
filter_slider("chla", "Chlorophyll-a", sd, column=~chla, step=0.1, width=250)
# use shared data with crosstalk widgets
bscols(
leaflet(sd) %>%
addTiles() %>%
addMarkers(),
datatable(
extensions = "Scroller", style="bootstrap", class = "compact", width = "100%", rownames = F,
sd, options =list(
scrollY = 300, scroller = TRUE,
columnDefs = list(
list(visible = F, targets = c(0:1, 4)),
list(className = 'dt-left', targets = '_all'))
),colnames = c('lat', 'lon', 'Bay segment', 'Station', 'mo', 'Chl-a (ug/L)')
) )
Observable is a relatively new approach that also allows dynamic features to be included in a Quarto document. It is an entirely separate language outside of R that uses JavaScript and allows excellent functionality similar what is provided by a Shiny Server. The following plot shows a histogram of chlorophyll values by bay segment that is created using the code below.
First, import the data as you would in R, then define variables for Observable using ojs_define()
. Note that Observable code chunks cannot be run interactively and only work when an entire Quarto document is rendered.
# import water quality data
<- readr::read_csv('https://github.com/tbep-tech/shiny-workshop/raw/main/data/tbwqdat.csv')
tbwqdat
# define variables
ojs_define(data = tbwqdat)
Then we create some selector widgets to filter by the range of chlorophyll values and data by individual bay segments.
```{ojs}
= Inputs.range(
viewof chla 1.8, 17.4],
[value: 1.8, step: 1, label: "Chlorophyll-a (ug/L):"}
{
)= Inputs.checkbox(
viewof bay_segment "OTB", "HB", "MTB", "LTB"],
[value: ["OTB", "HB", "MTB", "LTB"],
{ label: "Bay segments:"
}
)```
A filtering function is then created to filter the data based on the selections from the widget. Note use of the transpose()
function. This is required to use R data in a row/column format to an array format used in a JavaScript setting.
```{ojs}
= transpose(data)
datatr = datatr.filter(function(dat) {
filtered return chla < dat.chla &&
.includes(dat.bay_segment) ;
bay_segment
})```
Finally, we create the plot using the filtered data function.
```{ojs}
.rectY(filtered,
Plot.binX(
Ploty: "count"},
{x: "chla", thresholds: 10, fill: "bay_segment"}
{
)).plot({
x: {label: "Chlorophyll-a"},
color: {legend: true},
marks: [
.frame(),
Plot
]
}
)```
Additional information on using Observable with Quarto is available here.
A rendered HTML file can also be hosted online and shared by URL. This approach is useful to make the document available to anyone with the web address.
The easiest way to do this is to publish your document to RPubs, a free service from Posit for sharing web documents. Click the publish button on the top-right of the editor toolbar. You will be prompted to create an account if you don’t have one already.
This can also be done using the quarto
R package in the console.
::quarto_publish_doc(
quarto"data/quartoex.qmd",
server = "rpubs.com"
)
You can also use the Quarto CLI in the terminal. Here we are publishing the document to Quarto Pub.
Terminal
quarto publish quarto-pub data/quartoex.qmd
If your Quarto document is in an RStudio project on GitHub, you can also publish to GitHub Pages.
Terminal
quarto publish gh-pages data/quartoex.qmd
In this module we learned the basics of creating dynamic documents with Quarto that combine markdown text with R code. There’s much, much more Quarto can do for you. Please visit https://quarto.org/ for more information on how you can use these documents to fully leverage their potential for open science.