Working with Quarto

How to generate reproducible reports and computational notebooks

Published

05-Feb-2025

1 Introduction

The Quarto format (.qmd) is a multi-functional format, which is especially useful for scientific coding and analyses. Quarto documents can be used both to save and execute code as well as generating reports in various output formats. This is done by mixing markdown and so-called code chunks in the same document (we have course materials for markdown if you are unfamiliar with this format). The code itself as well as the output it generates can be included in the final report. Not only can Quarto work great for scientific coding, but can also be used for things such as presentation and websites - this entire workshop website is, in fact, created using only Quarto!

Quarto makes your analysis more reproducible by connecting your code, figures and descriptive text. You can use it to make reproducible reports, rather than e.g. copy-pasting figures into a Word document. You can also use it as a notebook, in the same way as lab notebooks are used in a wet lab setting (or as we utilise Jupyter notebooks in the tutorial after this one). Quarto itself does not require any particular programming language to be installed - any language you want to use can be installed separately. The currently supported languages are R, Python, Julia and Observable. Quarto is fully compatible with both R Markdown and Jupyter documents.

This tutorial depends on files from the course GitHub repo. Take a look at the setup for instructions on how to set it up if you haven’t done so already. Place yourself in the workshop-reproducible-research/tutorials/quarto/ directory, activate your quarto-env Conda environment and start your text editor or IDE of choice.

A note on R Markdown

Quarto is an evolution of the R Markdown format, which was previously used in this course. While R Markdown is a widely-used and excellent software for code and reports, Quarto is most easily thought of as “R Markdown 2.0”. If you’re familiar with R Markdown, you will find Quarto to be highly similar. The creators of both Quarto and R Markdown (Posit) have stated that R Markdown is not going to be deprecated, but most newer features will only come to Quarto. This means that if you’ve used R Markdown in the past now is a good time to make the switch, but you don’t have to. You can check out the Quarto website for more in-depth discussions regarding Quarto/R Markdown (dis-)similarities.

Python and R paths

To be sure that Quarto uses the Python and R installations in the quarto-env environment, you can set the environmental variables QUARTO_PYTHON and QUARTO_R to the paths of the Python and R executables in the quarto-env environment.

Activate the quarto-env environment and run the following commands in the terminal:

export QUARTO_PYTHON=$CONDA_PREFIX/bin/python
export QUARTO_R=$CONDA_PREFIX/bin/R

2 The basics

Let’s start with creating basic Quarto document that we can work with.

2.1 Creating Quarto documents

Quarto documents are just plain text files with the .qmd extension. Create a new file called e.g. quarto-tutorial.qmd and copy the following into it:

quarto-tutorial.qmd
---
title: "Untitled Quarto Document"
author: "Jane Doe"
format: html
---

This is a so-called YAML header, which is where we specify the general settings of the document in the form of key: value. The title and author are just what they sound like, while the format field specifies what type of output you want the final report to be in (alternatives include pdf, revealjs and many others). Here we have specified that we want HTML output, which is perhaps the most useful for scientific computing.

  • Change the title to My first Quarto document and the author to your name.

Let’s add some actual content to the document, starting with some basic markdown:

  • Add some text into your Quarto document (including an empty line between the YAML header and the text), e.g. the following:
quarto-tutorial.qmd
This is my first Quarto document!

# This is a header

This is where I'll soon add some *code* related to the first header.

Let’s see what this document looks like when it’s rendered into HTML by Quarto:

  • Go to the command line and type quarto render quarto-tutorial.qmd.
Rendering

If you’re using e.g. RStudio or VSCode to edit your Quarto document you might have access to a render button, which means you don’t have to run the above command from the command line if you prefer.

Open your new quarto-tutorial.html file that was created and see what it looks like. It’s only markdown content so far, so let’s add some R code using a code chunk. Add the following to the quarto-tutorial.qmd file:

quarto-tutorial.qmd
```{r}
Sys.Date()
```

Notice that we delimit the code chunk from the rest of the document’s contents using three backticks (```) and specify the R language using curly brackets ({r}). The code itself just prints the current date.

  • Render the document again and see what it looks like.

You can also name chunks by adding it after the language:

quarto-tutorial.qmd
```{r date}
Sys.Date()
```

This is useful for debugging when something has gone wrong, since it’ll be easier to see exactly which code chunk an error happened (instead of just showing the chunk as a number).

We can also get in-line code using {r} <R CODE>, like so:

quarto-tutorial.qmd
The current date is `{r} Sys.Date()`.
  • Add the example above and render the document again to make sure it worked.

2.2 Previewing documents

Quarto has a highly useful command for when you’re working on a document: preview. It’s essentially a live preview of the document you’re working on that will automatically render when you introduce changes to the document.

  • Type quarto preview quarto-tutorial.qmd in the command line.

Your default web browser should now have opened a new window with your rendered document, while your command line should say something like the following:

Watching files for changes
Browse at http://localhost:4175/

You can’t type new commands at the moment, because the Quarto Preview command is still running - it’s watching for any new changes to the Quarto document you specified.

  • Change or add some markdown text to your Quarto document, e.g. This is a code chunk instead of the previous text under the first header. Make sure you save the document.

The HTML document in your browser should have updated to reflect your newest changes automatically. Previewing documents is great when you want to have continuous feedback to the changes you make and can make the process of writing more seamless, since you don’t have to manually render all the time. Previewing will still render the entire document, however, meaning that if you have some heavy computations you might not want to re-render on every single save. For those cases you might instead prefer to stick with manual rendering when you are satisfied with multiple changes. You can abort a preview like any on-going command, e.g. using Ctrl-C.

In the rest of the tutorial it’s up to you whether you want to use preview or not - the tutorial will just mention when it’s time to render, you decide how that’s done.

2.3 Rendering to PDF

So far we’ve only rendered to HTML, but sometimes you prefer a PDF. This entails changing the format option in the YAML header:

  • Change the format to pdf in the header and render your document.

You can add any raw LaTeX commands you want to your document when you’re rendering to PDF, e.g. \footnotsize to change the font size. You also have LaTeX-specific settings, such as setting the geometry for the whole document or specifying a citation method. While the details of LaTeX are outside the scope of this course, it’s useful to be aware of this functionality of Quarto so that you may use it if you already know LaTeX or if you want to learn it.

Switch back to HTML rendering before you move on.

2.4 Languages

The examples so far have been using R, but we could just as easily have used Python. All we have to do is to specify {python} as the code chunk language and its content to be the equivalent Python code. Try adding this to your document and render it again:

quarto-tutorial.qmd
```{python}
from datetime import date
print(date.today())
```
Quick recap

In this section you learned how to create, edit and render basic Quarto documents using different languages.

3 Code chunk options

Sometimes you want to add chunk options to the code chunks in your Quarto documents. They are also in YAML format and are prefixed with a special type of comment (#|). It can look something like this:

quarto-tutorial.qmd
```{python}
#| echo: false
from datetime import date
print(date.today())
```
  • Add the chunk option above to your document and render the document again.

Notice how we no longer see the code itself, just the output? This is because the echo option specifies just that: whether we see the code or not. There are a number of such chunk options that are useful to know about:

Chunk option Effect
echo Include the chunk code in the output.
eval Evaluate the code chunk.
output Include the results of executing the code in the output.
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 Prevent both code and output from being included.
  • Check what happens if you change echo: False to eval: False.

Now the code in the code chunk is not run but the code itself is shown in the rendered document.

3.1 Figure options

There are also options related to figures, but for that we need to actually have some code that produces a figure.

  • Add the following code chunk to your document (don’t worry if you don’t understand the R code itself, it’s just as example):
quarto-tutorial.qmd
```{r}
library("ggplot2")
library("palmerpenguins")
data(penguins, package = "palmerpenguins")
ggplot(penguins, aes(x      = bill_length_mm,
                     y      = body_mass_g,
                     colour = species)) +
    geom_point(size = 2) +
    theme_bw() +
    labs(x      = "Bill length (mm)",
         y      = "Body mass (g)",
         colour = "Species") +
    ggtitle("Penguin weight and bill length") +
    theme(plot.title = element_text(hjust = 0.5)) +
    scale_colour_manual(values = c("#c1dea0", "#85be42", "#425f21"))
```

Now render the document again. You should see both the code and a figure using the Palmer Penguins dataset. You should also see a warning along the lines of Removed 2 rows containing missing values.

  • Suppress the warning by adding #| warning: false as a chunk option and render the document again.

There are two chunk options related to figure sizes: fig-width and fig-height (expressed in inches). These allow you to experiment with your figures and make them look the way you want.

  • Add both the fig-width: 10 and fig-height: 5 chunk options and render.

You can also add captions and alt text using the fig-cap and fig-alt code chunk options respectively.

  • Add a suitable caption and alt text to the figure and render.

If you want to place the caption in the margin of your document you can use the cap-location chunk option.

  • Add cap-location: margin to your chunk options and render.
Note

On some quarto versions the cap-location: option may not work as expected. If you experience this, try also adding #| label: fig-penguins to the chunk.

3.2 Cross-references

A convenient way to be able to refer to figures in text is by adding a figure label, which will automatically add a figure number before your caption.

  • Add a suitable label, e.g. label: fig-penguins to the chunk options, then render the document again.

Notice that the figure now has a number before the caption. Importantly, the label must start with fig- for the numbering and cross-referencing to work.

Cross-references use the @ symbol and the corresponding label. You can thus write some markdown outside of a code chunk and refer to e.g. @fig-penguins, as per the example here. Try this out by adding the following to your document:

quarto-tutorial.qmd
A plot of penguin weight and bill length is shown in @fig-penguins.

then render the document again.

This is extremely useful if you’re writing a paper or a report where you want to refer to figures and content in the markdown text. Quarto even adds a clickable link to the figure itself as well!

3.3 Sub-figures

It’s also possible to create sub-figures using Quarto, instead of using whatever plotting library that your created the figures with.

  • Add the following (almost identical) code at the bottom of the chunk you already have:
ggplot(penguins, aes(x      = bill_depth_mm,
                     y      = body_mass_g,
                     colour = species)) +
    geom_point(size = 2) +
    theme_bw() +
    labs(x      = "Bill depth (mm)",
         y      = "Body mass (g)",
         colour = "Species") +
    scale_colour_manual(values = c("#c1dea0", "#85be42", "#425f21"))
  • Also add the following to the chunk options:
#| fig-subcap:
#|     - Bill length vs. body mass
#|     - Bill depth vs. body mass

You should now see that we have two figures with separate sub-captions as well as the overall figure caption we previously added. We can also control the layout of these figures using the layout-ncol chunk option.

  • Add a layout-ncol: 2 chunk option and render the document.

We now have a different, two-column layout instead, but whether you prefer this or just a one-column layout is up to you.

3.4 Tables

Tables work much in the same way as figures. It might, in our example, be nice to add a table with the data we previously plotted.

  • Add the following code chunk to your document and render it:
quarto-tutorial.qmd
```{r}
#| label: tbl-penguins
#| tbl-cap: Palmer penguins bill length, width and body mass.
#| tbl-cap-location: margin
knitr::kable(
    penguins[1:10, c("species", "bill_length_mm", "bill_depth_mm", "body_mass_g")],
    col.names = c("Species", "Bill length (mm)", "Bill depth (mm)", "Body mass (g)")
)
```
Quick recap

In this section you learned several chunk, figure and table options, how cross-referencing works and how to add sub-figures.

4 Document options

So far we’ve mostly worked with chunk options, which are specific to the chunk they appear in. You can set many of these at the global document level, however, and there are also some options specifically for tailoring the document as a whole, regardless of chunk content.

We’ve already looked at some global options, such as title, author and format. Something that would go nicely with the first two is the date option. You could just write the actual date if you like, or you can use the today option:

  • Add the following to the document options: date: today

4.1 Code folding

A useful option we haven’t touched already is the code-fold option. This and similar global options are specified nested inside the format option, like so:

format:
    html:
        code-fold: true
  • Add the code-fold option to your document and render it.

This can be a nice default to use in scientific reports, as it hides the code by default but is always there for those who want to inspect it. You can also use the code-summary chunk option to specify a different text to show with the folded code instead of the default Code, e.g. code-summary: Click to show code.

If you want to add the code-summary option to all chunks you can add the following to the yaml header:

language:
  code-summary: Click to show code

You can also add the code-tools option, which will add a drop-down menu to toggle visibility of all code as well as the ability to view the source of the document.

  • Add the code-tools: true option and render the document.

4.2 Table of contents

Another useful document option is to add a table of contents, which can be done with the toc option. This will automatically populate the table of contents using the headers from your document.

  • Add some more headings and/or sub-headings to your document.

  • Add the toc: true option to the html format and render.

The table of contents is to the right of the document by default, but you can change it using toc-location. The toc-depth allows you to control how many sub-heading levels are included in the table of contents.

  • Add toc-location: left and toc-depth: 2 to your document and render it.

Having the table of contents on the left can be useful if you are using the margins for something, such as we are doing in this tutorial. You can similarly add section numbering using number-sections and number-depth. Smooth scrolling is not enabled by default, but you can add it using smooth-scroll: true. You can change the title of the table of contents using toc-title.

  • Add section numbers, depth, smooth scrolling and a different table of contents title to your document and render it.

4.3 Themes

Quarto has a lot of themes available for it.

  • Add theme: flatly under the HTML format option and render.

If you want to get real advanced you can play around with lots of details regarding the themes and adjust as you see fit, or even just create your own theme. This is a bit too advanced to go through here, but you can read about it more in the official documentation.

4.4 Global chunk options

The chunk options we learnt about in the previous section of this tutorial can also be specified on the global document level. Instead of specifying e.g. warning: false or fig-height: 5 in individual chunks we can add it to the main YAML header in the same manner as for e.g. code folding or table of contents. We’ll still have to specify options like labels or captions at the chunk-level, though.

  • Add warning: false to your document header and remove it from the penguin figure chunk you already have.

4.5 Embedding HTML resources

When rendering HTML documents you get any figures and other resources in a <document-name>_files/ directory, which is not always desirable. It’s easier to move the HTML around if all figures etc. are embedded directly in the HTML itself, which can be done by specifying embed-resources: true in the HTML format options. This option is false by default, meaning that you’ll also have to include the previously mentioned directory if you want to share the HTML with anybody.

  • Remove the <document-name>_files/ directory, refresh the rendered document and see what happens.

  • Add the embed-resources option and render your document again.

What happened first is that your figures should have disappeared when you deleted the resources directory. Embedding resources and rendering again should not re-create this directory, so now you’ll just have a stand-alone HTML file that is more portable than before.

4.6 Multiple formats

So far we’ve mostly been working with HTML output, but you don’t need to limit yourself to a single output format if you don’t want to.

  • Add the docx: default line in the format: part of your YAML header and render your document.

You should have gotten two separate output files now: a HTML and a DOCX (Word) file. You can specify further options for any of the formats you include, instead of just using the default settings as in this example.

  • Render your document again, but supply the --to html flag.

This will only render to the specified output format, which is highly useful when you want to write a Quarto document with more than one format but not always render them all.

4.7 Parameters

The last document-wide option we’ll touch on is parameters. This is useful for when you want to be able to run the same document with different parameters or options for some computations. Parameters are specified using the params option:

  • Add the following code to your YAML header:
params:
    point_size: 2
  • Also change the hard-coded geom_point(size = 2) to geom_point(size = params$point_size) in the two ggplot calls in the first code chunk.

We have thus specified a parameter called point_size in the YAML header and referred to it in the code using params$point_size. You can now change this parameter at run-time by supplying the -P <param>:<value> (or --execute-param) flag to quarto render.

Notice that this won’t work if you want to use a parameter to control e.g. a chunk option like layout-ncol. For this we need to use an in-line code expression: #| layout-ncol: !expr params$ncols.

  • Add a parameter for the layout-ncol chunk option to the YAML header
  • Also add the layout-ncol chunk option to the figure chunk using the syntax above and render to make sure it works.

Note that to modify multiple parameters at run-time you have to use the -P param:value flag multiple times, like so:

quarto render quarto-tutorial.qmd -P point_size:4 -P ncols:1

You can also specify parameters in a params.yml file and instruct quarto to use them with the --execute-params params.yml flag when rendering. Note that the parameters must be defined in the YAML header, pointing quarto to a params.yml file with --execute-params only overrides them when rendering.

Using parameters is extremely useful when you’re using a workflow manager system (e.g. Snakemake or Nextflow), since you can easily specify sample-specific parameters from the command line directly from your workflow manager.

Quick recap

In this sections we covered a number of document-wide options, including code-folding, table of contents, theming, HTML portability, using multiple output formats and parameters.

5 Presentations

Quarto can also be used to create presentations in multiple formats such as reveal.js (HTML), beamer (PDF) and pptx (PowerPoint) - the most powerful of these formats by far is the first one. Creating presentations with Quarto is quite similar to creating general Quarto documents, with some added features to keep in mind.

5.1 Slides

The first thing that’s needed for creating a presentation is deciding what constitutes a slide. The default is that slides are delimited by a document’s header levels.

  • Render your document using the --to revealjs flag and open it.

You should now have the same document we’ve been working on for this tutorial in presentation format! You can step through the slides using the arrow keys, press F to go into full-screen mode, S to view speaker notes, M for the menu (you can also click in the lower left corner to get this menu) and ESC to go back.

If you’ve followed along you should have one level-1 header (#) and two level-2 headers (##). Notice that the level-1 header here will render as a blank page with just the header content on it, while the level-2 headers will render as normal slide headers. This all looks quite nice, and we didn’t even have to change a thing! Disregard that the table on the last slide doesn’t fit for now, we’ll get back to it later. Another method of delimiting slides is using a horizontal rule, ---, which allows you more fine-grained control over slides and their content (and is especially useful if you want to have a slide without a title).

5.2 Divisions

There are many ways you can add presentation-specific content to your slides, some of which you’d recognise from e.g. PowerPoint functionality.

So called “divisions” or “divs” allow you to control the appearance of content in your slides.

Let’s fix that issue with the table that was larger than the page. The problem here is one of content overflow, which can be fixed by adding a special {.smaller} div.

Note

Divs do not work for level1 headings (starting with a single #).

  • Add the {.smaller} div to the table header (it should read something like ## A table {.smaller}) and render.

That should have automatically re-sized the table to fit into the slide. Another way to solve this is to make slide content scrollable.

  • Change the {.smaller} div to a {.scrollable} div and render.

Instead of re-sizing the table we now get the ability to scroll down it instead; whichever solution you prefer is up to you.

Adding divisions of various types like this is a common thing for Quarto presentations. Another common presentation-functionality is incremental lists, which can also be achieved with divisions. When adding a division to slide content we specify the division’s content in a manner similar to a code chunk, like in the following example:

quarto-tutorial.qmd
## Penguin species

::: {.incremental}
 - Adelie
 - Chinstrap
 - Gentoo
:::
  • Add the code above to your document and render it.

Stepping through incremental content works the same as for stepping through slides, i.e. using the arrow keys.

  • Render your document to html instead of revealjs.

Notice that Quarto rendered the HTML document just fine, even though you now have some presentation-specific code? This allows you to switch between the formats on-demand without having much overhead or format-specific code, which is great when you want to present your work without having to whip out a full-fledged presentation and all the work that goes into that!

There are other useful divisions as well, including {.notes} (speaker notes), {.aside} (additional commentary similar to footnotes), {.footer} (slide footers), which you can add in the same way as we did for the incremental list above.

  • Pick one of the above-mentioned divisions to add to your presentation and render it.
Note

The notes and footer divisions will appear as normal Markdown text when rendering to HTML, while asides will appear in the margin. These divisions thus represent cases you might want to avoid if you want to be completely format-agnostic.

5.3 Presentation options

Just like the other formats you can specify presentation-specific options at the document-level using the YAML header. You could, for example, add the {.scrollable} or {.smaller} div to the entire document.

  • Add the revealjs format to the YAML header as well as a scrollable: true option to it.

You can also specify one of the built-in themes here.

  • Add theme: simple to your YAML header and render.

You can find the entire list of themes at the Quarto website.

5.4 Multiple columns

Sometimes you’ll want to have more than one column in your presentation, which is done with the {.columns} and {.column} divisions. The former specifies that a section with multiple columns is starting, while the second specifies when each column starts, like so:

quarto-tutorial.qmd
:::: {.columns}

::: {.column}
Left column
:::

::: {.column}
Right column
:::

::::
  • Add multiple columns with some content to your presentation and render it.

You can also control the widths of these columns using e.g. {.column width="40%"}.

Note

The {.columns} div also works for a normal HTML render, so it’ll look the same regardless of whether you output as a document or a presentation.

5.5 Fragments

We’ve already learnt how to get incremental lists working, but what about general content we want to incrementally step through? This is done with the {.fragment} div.

  • Add a {.fragment} div to some slide content and render.

Fragments are similar to “animations” from PowerPoint and come with lots of built-in variations, e.g. fade-out, grow, strike and several others.

  • Add a fragment variant to your content, e.g. {.fragment .grow} and render your document.

You can also control the order in which fragments appear using the fragment-index=<NUMBER> option.

  • Create a new slide and add some content with a different order of appearance than the order of the code. If you need help or inspiration, click below.
## Why Palmer Penguins?

::: {.fragment fragment-index=2}
![](https://allisonhorst.github.io/palmerpenguins/logo.png){fig-align="center"}
:::

::: {.fragment fragment-index=1}
The goal of `palmerpenguins` is to provide a good dataset for data exploration
and visualization, as an alternative to `iris.`
:::
Quick recap

In this section we covered how to create presentations using Quarto, including how to add various divisions, global slide-options, multiple columns and fragments.

6 Extra material

The following material contains some more advanced things that you can do with Quarto but are not really part of the core of the Quarto material. It’s a mix of various functionalities, and you don’t have to go through it if you don’t want to.

If you’re interested in learning more about Quarto in general, here are some reading tips:

6.1 Tabsets

Sometimes you’ll want to present the same content in different ways, e.g. the equivalent code in different languages. Look at the following toy example:

::: {.panel-tabset}
## R
```{r}
words <- c("Foo", "bar")
print(paste(words), collapse = ' ')
```

## Python
```{python}
words = ["Foo", "bar"]
print(' '.join(words))
```
:::

Try adding that to a document and see that you’ll get a set of tabs that change the content of the code chunk to the respective language. This is not only useful for showing different languages, but can be used for other situations as well. For example, you might want to run different analyses and show them in different tabs, or even show different interactive elements in separate tabs.

6.2 Callouts

If you’re writing some sort of documentation, tutorial or just want to draw special attention to something, callouts are here for you. They render as a coloured block with a header and content. There are five types of callouts: note, tip, warning, caution, and important. As with lots of Quarto things they are specified using a division, like so:

::: {.callout-note}
This is a note callout.
:::

The different callouts come with appropriate colours by default, which you can change in the theme. You can also have collapsible callouts by adding the collapse=true option, where true will have the callout collapsed by default. You can also specify titles in the same way using the title=<TITLE> option or by adding the title directly to the callout content, like so:

::: {.callout-note}
## This is the callout title

This is a note callout.
:::

You can change the overall appearance of callouts by using the appearance option or the callout-appearance global option. Valid values are default, simple and minimal, with decreasing usage of colours and weights. You can also suppress the callout icons using icon=false or callout-icon: false in a similar manner.

6.3 Python code

So far we’ve used Quarto with R-code chunks, but Quarto also supports Python. While R-code is executed with the Knitr engine, Python code can be executed using either Jupyter or Knitr + the reticulate package.

To try out Python code in Quarto, make a new document called quarto-python.qmd and add the following to it:

quarto-python.qmd
---
title: "Python in Quarto"
format: html
---

This is a Quarto document with Python code!

```{python}
from datetime import date
print(date.today())
```

Here is how you'd use inline code to print today's date: `{python} date.today().strftime("%Y-%m-%d")`.

Save and render the document with quarto render quarto-python.qmd.

You probably saw that Quarto reported:

Starting python3 kernel...Done

This is because Quarto automatically determined that it should use a Jupyter kernel to execute the code in the document. You can read more about how this works here.

The quarto-env conda environment that you installed for this tutorial comes with the default IPython kernel, but you can install additional kernels for other coding languages or containing specific packages.

To see which kernels are available on your computer, run jupyter kernelspec list on the command line. If you haven’t installed any kernels before you should just see the python3 kernel which is the one contained in the quarto-env environment and the one Quarto used to render the document above.

If you want to explicitly instruct Quarto to use the python3 kernel you can add jupyter: python3 to the document YAML header. However, this requires that you have the quarto-env environment activated. If you activate another conda environment with the jupyter package installed, the python3 kernel used for rendering will be the one in that environment.

To get around this, you can install the kernel in an active conda environment under a unique name using the following command:

python -m ipykernel install --user --name=KERNEL_NAME

where KERNEL_NAME can be any name you want. Try this out with the quarto-env environment. Run:

python -m ipykernel install --user --name=quarto-env

Now specify the kernel name in the YAML header of your Quarto document:

jupyter: quarto-env

and render the document again.

6.4 Mixing R and Python

Another way to execute Python code in Quarto documents is to use the reticulate package in R. This also allows you to use R objects such as dataframes in Python code chunks and vice versa. The r-reticulate conda package is already installed in the quarto-env environment, so you can try this out directly in the quarto-python.qmd document you created above.

Change the YAML header in quarto-python.qmd to instruct Quarto to use the Knitr engine. The header should look like this:

quarto-python.qmd
---
title: "Python in Quarto"
format: html
engine: knitr
---

Also add the following R code chunk to the end of the document:

quarto-python.qmd
```{r}
library("palmerpenguins")
library("reticulate")
data(penguins, package = "palmerpenguins")
penguins <- penguins[!is.na(penguins$body_mass_g),]
head(penguins)
```

Render the document again. In the R code chunk we load the penguins dataset, remove rows with missing values and printed the first few rows. As you can see, both the Python and R code chunks are executed in the same document. You’ll also notice that the inline Python code could not be executed. This is currently a limitation of Knitr.

Now add the following Python code chunk:

quarto-python.qmd
```{python}
import pandas as pd
penguins = r.penguins
penguins["body_mass_kg"] = penguins["body_mass_g"] / 1000
penguins.head()
```

and render the document again.

This code chunk takes the penguins dataframe from R (penguins = r.penguins) and adds a new column with the body mass in kilogram then prints the first few rows.

We can also pass the modified dataframe back to R. Add the following code chunk:

quarto-python.qmd
```{r}
#| fig-width: 10
#| fig-height: 5
#| label: fig-penguins
#| fig-cap: "Penguin weight and bill length"
#| fig-alt: "A scatter plot of penguin weight and bill length"
#| cap-location: margin
library("ggplot2")
penguins_py <- py$penguins
ggplot(penguins_py, 
    aes(x = bill_length_mm,
        y = body_mass_kg,
        colour = species)) +
    geom_point(size = 2) +
    theme_bw() +
    labs(x = "Bill length (mm)",
            y = "Body mass (kg)",
            colour = "Species") +
    ggtitle("Penguin weight and bill length") +
    theme(plot.title = element_text(hjust = 0.5)) +
    scale_colour_manual(values = c("#c1dea0", "#85be42", "#425f21"))
```

then render the document again.

In this code chunk the modified dataframe is passed to R (penguins_py <- py$penguins) and used to create a scatter plot of penguin weight (in kilograms) and bill length.

You can read more about the reticulate package in the documentation.

6.5 Citations

You can actually write whole articles in Quarto! For that purpose, it’s also great that you can cite things from a bibliography as well. Specifying the bibliography file(s) is done using the bibliography global option; specifying the citation style can be done using a csl (Citation Style Language) file and the csl global option. Citation itself is similar to cross-referencing (@cross-ref), but is surrounded by square brackets: [@citation]. You can read more details about citations at the Quarto website.