Skip to main content

Documents

Misc

  • Packages

    • {quarto}
    • {brand_yml} - Create reports, apps, dashboards, plots and more that match your company’s brand guidelines with a single _brand.yml file
      • For Quarto dashboards, websites, reports, etc.
      • For Python shiny, seaborn, matplotlib, etc.
      • For R shiny, ggplot2, plot, RMarkdown
    • {froggeR} - Reusable templates and project structures
      • Enhanced Quarto Project Creation
        • Creates skeleton of project files. These files can also be created with individual functions (See below)
      • Reusable YAML Headers
      • Templated Documents
      • .gitignore, SCSS, RProj, README templates
    • {litedown} - A lightweight version of R Markdown
      • Control number of rows printed (source)
        • Global

          options(xfun.md_table.limit = N)
          • Where N is the number of the maximum number of rows you want printed.
        • Chunk

          ```{r print.args = list(data.frame = list(limit = N)}
          # stuff
          ```
          • You can substitute ‘data.frame’ with the class of your data object to be printed
    • {cocoon} - Extract, Format, and Print Statistical Output into inline Rmd/qmd documents
    • {r2resize} - Elements (pop-ups, cards, images, etc.) with various interactive resizing features
  • Resources

  • Tools

    • qvm - Quarto Version Manager
    • Panache - A language server, formatter, and linter for Pandoc, Quarto, and R Markdown.
      • Built for fast, reliable formatting and robust parsing across syntax that many generic Markdown tools struggle with, including fenced divs, grid tables, definition lists, citations, and inline footnotes.
  • quarto --version - Must be in RStudio Terminal

  • quarto check - Must be in RStudio Terminal - versions and engine checks

    $ quarto check
    [>] Checking versions of quarto binary dependencies...
          Pandoc version 3.1.1: OK
          Dart Sass version 1.55.0: OK
    [>] Checking versions of quarto dependencies......OK
    [>] Checking Quarto installation......OK
          Version: 1.3.340
          Path: C:\Users\tbats\AppData\Local\Programs\Quarto\bin
          CodePage: 1252
    [>] Checking basic markdown render....OK
    [>] Checking Python 3 installation....OK
          Version: 3.8.1 (Conda)
          Path: C:/Users/tbats/Miniconda3/python.exe
          Jupyter: 4.9.1
          Kernels: python3
    (\) Checking Jupyter engine render....2023-04-28 10:18:15,018 - traitlets - WARNING - Kernel
    Provisioning: The 'local-provisioner' is not found.  This is likely due to the presence of multiple jupyter_client distributions and a        previous distribution is being used as the source for entrypoints - which does not include 'local-provisioner'.  That distribution should     be removed such that only the version-appropriate distribution remains (version >= 7).  Until then, a 'local-provisioner' entrypoint will     be automatically constructed and used.
    The candidate distribution locations are: ['C:\\Users\\tbats\\Miniconda3\\lib\\site-packages\\jupyter_client-5.3.4.dist-info',                'C:\\Users\\tbats\\Miniconda3\\lib\\site-packages\\jupyter_client-7.0.6.dist-info']
    [>] Checking Jupyter engine render....OK
    [>] Checking R installation...........OK
          Version: 4.2.3
          Path: C:/PROGRA~1/R/R-42~1.3
          LibPaths:
            - C:/Users/tbats/AppData/Local/R/win-library/4.2
            - C:/Program Files/R/R-4.2.3/library
          knitr: 1.42
          rmarkdown: 2.20
    [>] Checking Knitr engine render......OK
  • CLI

    • quarto render to compile a document
    • quarto preview to render a live preview that automatically updates when the source files are saved
  • Using a development verison of Quarto

    • First Usage
      • Change directories to where you want to store the dev version

      • Clone repo and change to the cloned directory

        git clone https://github.com/quarto-dev/quarto-cli
        cd quarto-cli
      • Disable Anti-Virus

      • Run Configuration Script

        • Windows Command Prompt

          cmd /k configure.cmd
          • \k keeps the window open in case it errors
        • Powershell

          Invoke-Item configure.cmd
        • Linux/MacOS

          ./configure.sh
        • This will take a minute or two as it checks versions, installs dependencies like pandoc, etc.

      • Add path to quarto.cmd to PATH

        • After the configuration file runs, it will output the path you need to put on PATH, e.g. "C:\Users\erc\Documents\Quarto\quarto-cli\package\dist\bin"
      • Enable Anti-Virus

      • Should be able to use in RStudio

        • I was not able to use the RStudio terminal for quarto commands (e.g. quarto check) though.
        • To find the version, I just opened powershell and ran quarto –version just to make sure it was running and on PATH.
          • Not sure if they use this every time but it was 99.9.9 instead of the verion in the changelog.
        • I also rendered a qmd file using quarto-cmd from the root directory of quarto-cli to see if it matched the output from RStudio. (cd qmd then quarto preview forecasting-statistical.qmd --to html --no-watch-inputs --no-browse)
    • Subsequent Development Versions
      • Change directory to quarto-cli and git pull
  • Shortcuts

    • New R chunk: ctrl + alt + i
    • Build whole book: ctrl+shift b
    • Render page and preview book: ctrl+shift k
  • For large documents (modularity, avoid caching) (source)

    1. Use R scripts that do data processing and modeling
    2. From those scripts, save plots and other outputs as RDS files
    3. In document, load RDS objects and make modifications.
  • Using yaml style for chunk options

  • Convert Rmd chunk options to Quarto: knitr::convert_chunk_header("doc.rmd", "doc.qmd")

  • Anchor Link - A link, which allows the users to flow through a website page. It helps to scroll and skim-read easily. A named anchor can be used to link to a different part of the same page (like quickly navigating) or to a specific section of another page.

    • This is the “#sec-moose” id that can be added to headers which it allows to be referenced within the document or in other documents.
  • MathJax commands

    • Font Size: \tiny{ }, \scriptsize{ }, \small{ }, \normal{ }, \large{ }, \Large{ }, \LARGE{ }, \huge{ }, \Huge{ }
  • Lightbox

    • Docs
    • Grouping images for lightbox carousel: ![A Lovely Image](mv-1.jpg){group="my-gallery"}
    • For a book project, you should set quarto options at the outer most level in _quarto.yml (e.g. not under format >> html)
  • Foldable (non-executable) Code Blocks

    • HTML Tags

      ![](image.png)
      
      <details>
      
      <summary>Code: My non-executable code</summary>
      
      ``` r
      # code
      ```
      
      </details>
  • Add an animated gif

    ```{r, echo = FALSE}
    knitr::include_graphics("man/figures/clusterpermute_animation.gif", 
                            error = FALSE)
    ```
  • Using variables and highlighting text

    ```{epoxy, .data=text_data_chunk_1_3}
    In {year}, measles elimination was <span class = "txt-navy">achieved</span> in {nb_achieved} countries in the WHO region, while it was <span class = "txt-yellow">re-established</span> in ...
    ```
  • Sharing documents with JS chunks

    • Quarto documents with embedded ObservableJS charts can run entirely in the browser, but if you email someone an HTML file with embedded JavaScript, it won’t run. Instead of the chart, they’ll get an error.
      • This is a (good) security feature, so that when you click on something, arbitrary JS code doesn’t start running on your laptop
    • Adding JS (e.g. for drop down filters etc.) is fine since it doesn’t call any external JS libraries.
  • Keyboard Shortcuts

    • Single keyboard shortcuts for every operating system use a positional parameter: {{< kbd Ctrl-C >}}
    • Different shortcuts for different operating systems use keyword parameters win, mac, and linux: {{< kbd mac=Shift-Command-O win=Shift-Control-O linux=Shift-Ctrl-L >}}

Syntax

  • Inline code

    -   Total number of counties: **`{r} polling_places |> filter(state == "Alabama") |> distinct(county_name) |> count()`**
    -   Total number of polling places: **`{r} polling_places |> filter(state == "Alabama") |> count()`**
    -   Election Day: **`{r} polling_places |> filter(state == "Alabama") |> pull(election_date) |> unique()`**
    • To escape backticks in inline code, you have to use double-backticks instead of single backticks

      • Example: To get "`"\$(\$file.FullName)`""

        `` "`"\$(\$file.FullName)`"" ``
  • Align code chunk under bullet and add indented comment below chunk

    -   [Example]{.ribbon-highlight} (using a SQL Query; method 1)
    
        ``` r
        # open dataset
        ds <- arrow::open_dataset(dir_out, partitioning = "species")
        # open connection to DuckDB
        con <- dbConnect(duckdb::duckdb())
        # register the dataset as a DuckDB table, and give it a name
        duckdb::duckdb_register_arrow(con, "my_table", ds)
        # query
        dbGetQuery(con, "
          SELECT sepal_length, COUNT(*) AS n
          FROM my_table
          WHERE species = 'species=setosa'
          GROUP BY sepal_length
        ")
    
        # clean up
        duckdb_unregister(con, "my_table")
        dbDisconnect(con)
        ```
    
        -   filtering using a partition, the WHERE format is '\<partition_variable\>=\<partition_value\>'
    • Space between bullet and top ticks
    • Space between bottom ticks and bullet
    • Note alignment of text
  • Add Code Annotations

    -   [Partition a large file and write to arrow format]{.underline}
    
        ``` r
        lrg_file <- open_dataset(<file_path>, format = "csv") # <1>
        lrg_file %>%
            group_by(var) %>% # <2>
            write_dataset(<output_dir>, format = "feather") # <3>
        ```
    
        1.  Pass the file path to `open_dataset()`
    
        2.  Use `group_by()` to partition the Dataset into manageable chunks
    
        3.  Use `write_dataset()` to write each chunk to a separate Parquet file---all without needing to read the full CSV file into R
    
        -   `open_dataset` is fast because it only reads the metadata of the file system to determine how it can construct queries
  • Footnote

    words [^1]
    
    [^1]: Data from https://github.com/rfordatascience/tidytuesday
  • For PDF output, you need pagebreaks:

    {{< pagebreak >}}
  • Reference Figure

    1 See polling place locations in @fig-statemap.

Functions

  • Tables with markdown

    • kable table

      data.frame(
        Feature = c("Formatting", "Math", "Links"),
        Example = c(
          tbl_qmd_span("**Bold**, *italic*"),
          tbl_qmd_span("$E = mc^2$"),
          tbl_qmd_span("[Quarto docs](https://quarto.org)")
        )
      ) |>
        knitr::kable(format = "html", escape = FALSE)
  • Converting Quarto to R

    # Extract R code from a Quarto document
    qmd_to_r_script("analysis.qmd")  # Creates "analysis.R"
    
    # Specify custom output
    qmd_to_r_script("analysis.qmd", script = "extracted-code.R")
    • It preserves cells options, commenting cells with eval: false, and ignoring content having purl: false

    • For documents using advanced knitr features like child= chunks or knitr::read_chunk(), knitr::purl() remains the recommended approach as it handles these through actual document processing.

  • Converting R to Quarto

    # Add metadata for rendering
    add_spin_preamble("analysis.R", 
                      title = "Analysis Report",
                      preamble = list(author = "Data Team"))
    
    # Now render the script with Quarto
    quarto_render("analysis.R")
  • Paths

    # Build paths relative to the Quarto project root
    data_file <- project_path("data", "analysis.csv")
    
    # Explicitly find the project root (searches for _quarto.yml)
    root <- find_project_root()
    
    # In posts/2025/analysis/report.qmd, this resolves to ../../../data/results.csv
    results <- read.csv(project_path("data", "results.csv"))

YAML

  • Set global chunk options in yaml

    • For code cells

      execute:
        echo: false
        message: false
        warning: false
  • Enable Margin Notes

    ---
    # YAML front matter
    reference-location: margin
    ---
  • !expr to render code within chunk options

    • e.g. figure caption: #| fig-cap: !expr glue::glue("The mean temperature was {mean(airquality$Temp) |> round()}")
  • column: screen-inset yaml markup is used to show a very wide table

  • If you haven’t set your Quarto document to be self-contained, then the images have also already been saved for you - probably in a folder called documentname_files/figure-html/

    format: 
      html:
        embed-resources: true
  • Date first published and date modified using the current date:

    ---
    date: 2024-01-01
    date-modified: today
    ---
  • YAML Examples

    • Example
  • For Standalone HTML Documents with htmlwidgets, make sure to set embed-resources: true

    ---
    format:
      html:
        embed-resources: true
    ---
  • Switch for light/dark mode (source)

    ---
    format:
      html:
        theme:
          light: litera
          dark: darkly
    ---
    • Places a button at the top of the document that enables the reader to select between the two modes

    • See source for details on customization

    • See Theme Helpers for setting themes for both light/dark in tables, plots, and {brand.yml}

Chunk Options

  • Graphics

    • Code Chunk

      #| label: "fig-statemap"
      #| dpi: 300
      #| fig.height: 7.2
      #| fig.width: 3.6
      #| dev: "png"
      #| echo: false
      #| warning: false
      #| message: false
      • Example shows settings for a graph for mobile
      • fig.height and fig.width are always given in inches
    • Set Figure Height and Width Dynamically

      ```{r}
      if(params$country == "Somalia") {
        map_width <- 5
        map_height <- 4
      } else {
        ...
      }
      ```
      stuff and more stuff
      
      ```{r}
      |# fig-width: !expr map_width + .5
      |# fig-height: !expr map_height
      ```
  • Dynamic Fig Captioning (via rmflight)

    ```{r}
    #| label: fig-each
    #| fig-cap: !expr glue::glue('Number of things in {multi}.')
    #| fig-keep: all
    purrr::walk(multi, \(in_item){
      tmp = big_df |>
                   dplyr::filter(value %in% in_item)
      print(ggplot(tmp, aes()) + geom_point())
    })
    ```
  • Conditional Code Chunk Evaluation

    • Example: document output type

      • Set value in a code chunk

        ```{r setup}
        # Include in first chunk of .qmd
        # Get output file type
        out_type <- knitr::opts_knit$get("rmarkdown.pandoc.to")
        ```
      • Use !expr sytax to determine evaluation status

        • Example: eval chunk based on output type

          ```{r}
          #| eval: !expr out_type == "html"
          
          # code to create interactive {plotly}
          ```
          
          ```{r}
          #| eval: !expr out_type == "docx"
          
          # code to create static {ggplot2}
          ```
    • Example: Use parameterization to set value

      ---
      title: "test"
      format: html
      params:
        my_value: false
      ---
      • my_value can then be used throughout the document to determine chunk evaluation status

Knitr Hooks

  • Docs
  • Notes from Writing knitr hooks
    • Also has a knitr hook example that alters cell output (e.g. only prints 4 lines of a vector)
  • Chunk Hooks
    • Chunk hooks get called twice: once before knitr executes the code in the chunk, and once again afterwards

    • The function can take up to four arguments, all of which are optional:

      • before: A logical value indicating whether the function is being called before or after the code chunk is executed
      • options: The list of chunk options
      • envir: The environment in which the code chunk is executed
      • name: The name of the code chunk option that triggered the hook function
    • The chunk hook is called for its side effects not the return value. However, if it returns a character output, knitr will add that output to the document output as-is.

    • Example: Chunk Timer

      • Code

        create_timer_hook <- function() {
          start_time <- NULL
          function(before, options) {
            if (before) {
              start_time <<- Sys.time()
            } else {
              stop_time <- Sys.time()
              elapsed <- difftime(stop_time, start_time, units = "secs")
              paste(
                "<div style='font-size: 70%; text-align: right'>",
                "Elapsed time:", 
                round(elapsed, 2), 
                "secs",
                "</div>"
              )
            }
          }
        }
        knitr::knit_hooks$set(timer = create_timer_hook())
        • The hook is triggered the first time (with before = TRUE) to record the system time somewhere (e.g., in a variable called start_time). Then, when the hook is triggered the second time (with before = FALSE), it records the system time again (e.g., as stop_time), and computes the difference in time.
      • Use in a cell

        ```{r}
        #| timer: true
        runif(10000)
        ```
      • Output

  • Option Hooks
    • Runs before code in code chunk runs

    • Example: Figure String Interpolation (source)

      knitr::opts_hooks$set(fig.cap = function(options) {
        if (!is.null(options$fig.cap)) {
        options$fig.cap <- glue::glue(options$fig.cap)
      }
      
      return(options)
      })

Multiple Programming Languages

  • If only R or R and Python, the notebook is rendered by {knitr}

  • If only Python, the notebook is rendered by jupyter

  • Using ? operator to use a variable from a R chunk in a SQL chunk (source, article, docs)

    ```{r}
    #| cache: false
    db_file <- file.path(tempdir(), "metadata.ducklake")
    work_dir <- file.path(tempdir(), "lake_data_files")
    ```
    
    ```{sql}
    #| connection: con
    #| cache: false
    #| results: hide
    INSTALL ducklake;
    ATTACH ?db_path AS my_ducklake (DATA_PATH ?work_dir);
    USE my_ducklake;
    ```
    • con is the db connection variable
  • Set-up

    • {reticulate} automatically comes loaded in Quarto and it knows to use it when it sees a python block, so you don’t need to load the package
    • Quarto will select a version of Python using the Python Launcher on Windows or system PATH on MacOS and Linux. You can override the version of Python used by Quarto by setting the QUARTO_PYTHON environment variable.
      • In CLI on Windows, type py is see which version the Python Launcher , and therefore Quarto, is using and py –list to see which versions are installed.
  • R

    ```{r}
    #| label: read-data
    #| echo: true
    #| message: false
    #| cache: true
    lemurs <- readr::read_csv('https://raw.githubusercontent.com/rfordatascience/tidytuesday/master/data/2021/2021-08-24/lemur_data.csv')
    ```
  • Python

    ```{python}
    #| label: modelling 
    #| echo: true 
    #| message: false
    
    lemur_data_py = r.lemur_data 
    import statsmodels.api as sm 
    y = lemur_data_py[["Weight"]] 
    x = lemur_data_py[["Age"]] 
    x = sm.add_constant(x) 
    mod = sm.OLS(y, x).fit() 
    lemur_data_py["Predicted"] = mod.predict(x) 
    lemur_data_py["Residuals"] = mod.resid`
    ```
    • Use r. to access the data in the R chunk
    • The first execution of a python cell starts reticulate::repl_python() in the terminal
  • (back to) R

    ```{r}
    #| label: plotting 
    #| echo: true 
    #| output-location: slide 
    #| message: false 
    #| fig-align: center 
    #| fig-alt: "Scatter plot of predicted and residual values for the fitted linear model." 
    
    library(reticulate) 
    library(ggplot2) 
    lemur_residuals <- py$lemur_data_py 
    ggplot(data = lemur_residuals, aes(x = Predicted, y = Residuals)) +
      geom_point(colour = "#2F4F4F") +
      geom_hline(yintercept = 0,
                colour = "red") +
      theme(panel.background = element_rect(fill = "#eaf2f2", colour = "#eaf2f2"),
            plot.background = element_rect(fill = "#eaf2f2", colour = "#eaf2f2"))
    ```
    • Use py$ to access the data in the Python chunk *
    • Must call library(reticulate) in order for Quarto to recognize py$
  • Use embed shortcode to add more than one programming language engine to a document (source)

    ---
    format:
      html:
        embed-resources: true
    engine: knitr
    ---
    
    ::: {.panel-tabset .nav-pills}
    ## R
    
    ```{r}
    print("Hello World, from R")
    ```
    
    ```{r}
    #| fig-align: "center"
    x <- seq(-10,10, by = 0.1)
    y <- x ^ 3
    plot(x, y, type = "l")
    ```
    
    ## Python
    
    {{< embed python-code-using-jupyter-python3-engine.qmd echo=true >}}
    
    ## Stata
    
    {{< embed stata-code-using-jupyter-nbstata-engine.qmd echo=true >}}
    
    ## Julia
    
    {{< embed julia-code-using-julia-engine.qmd echo=true >}}
    
    :::

Layouts

  • 2 cols (1 col: text, 1 col: image)

    ::: {layout="[50,50]"}
    
    ::: column
    Every Quarto project starts with a Quarto file that has the extension `.qmd`.
    
    
    This particular one analyzes children's early words, but every `.qmd` includes the same three basic elements inside:
    
    
    - A block of metadata at the top, between two fences of `---`s. This is written in [YAML](https://learnxinyminutes.com/docs/yaml/). 
    - Narrative text, written in [Markdown](https://commonmark.org/help/tutorial/). 
    - Code chunks in gray between two fences of ```` ``` ````, written with R or another programming language.
    
    
    You can use all three elements to develop your code and ideas in one reproducible document.
    :::
    
    ![](img/01-source.png)
    :::
  • 2 figures, 2 columns (i.e. side-by-side) with captions at the top

    ---
    fig-cap-location: top
    ---
    
    -   Words
        -   Predictions of Standard RF vs Oblique RF
    
            ::: {layout-ncol="2"}
            ![Standard Random Forest](_resources/Regression,_Survival.resources/ml-rf-obl-vs-axis-axpred-1.png){fig-align="left" width="432"}
    
            ![Oblique Random Forest](_resources/Regression,_Survival.resources/ml-rf-obl-vs-axis-oblpred-1.png){fig-align="left" width="432"}
            :::
    
            -   Words  
    • fig-cap-location: bottom is default;
    • fig-cap-location: margin is buggy, at least in for project type book. Captions are added to the margins but bullet points mysteriously disappear during rendering to html
  • 2 charts side-by-side extending past body margins

    ```{r}
    #| label: my-figure
    #| layout-ncol: 2
    #| column: page
    ggplot() + ...
    ggplot() + ...
    ```
    • “layout-ncol” says 2 side-by-side columns
    • “column: page” says extend column width to the width of the page
  • Tabs

    -   Stuff
        -   More Stuff
    
    ::: panel-tabset
    ## tab title 1
    
    ``` r
    # code
    ```
    
    ## tab title 2
    
    words
    
    ``` r
    # other code
    ```
    -  Thoughts
    :::
    
    -   Stuff
  • Nested Tabs

  • Callout Blocks

    • Resources

    • Example: Todo

      ::: {.callout-note collapse="true"}
      ## todo
      
      1.  Finish video
          -   Currently working on: multinomial
      2.  Figure out exactly what $e$ is in the weight formula
      3.  Organize note
      4.  Transfer PS Matching section from econometrics-general
      :::
    • Example: Caution

      ::: callout-caution
      This note is unfinished. I still have more to add, and the concepts need to be organized.
      :::
  • Landscape Mode

    • Docs

    • In docx, pdf, and typst formats, you can set portions of the document to landscape mode by wrapping the content around a fenced div

    • Syntax

      This will appear in portrait mode.
      
      ::: {.landscape}
      
      This will appear in landscape.
      
      :::
      
      This will appear in portrait mode again.

Automation

  • Misc

    • Using External R FIles (source)

      • Use source

        ```{r}
        source("../code/functions.R")
        ```
      • Chunk Option

        ```{r}
        #| file: R/functions.R
        ```
        • Also see Include shortcode below
        • The file path should be relative to where your Quarto document is, and you need to make sure you set eval: true either in the code block, or document-wide.
    • Use dataframes as parameter inputs

      • Not recommended. Should used files (e.g. csvs) instead.

      • Using serialization

      • Using get

        ---
        title: "Data as a parameter"
        params:
          dataset: "mtcars"
        ---
        
        ```{r}
        head(get(params$dataset))
        ```
    • Print out the code of a function from a file (source)

      ```{r setup, include=FALSE}
      knitr::opts_chunk$set(echo = TRUE)
      
      inline_function_df <- function(f) {
        lines <- attr(f, "srcref")[c(1,3])],
        source <- attr(attr(f, "srcref"), "srcfile")
        source$lines[seq(lines[1], lines[2])]
      }
      
      source("R/functions.R", keep.source = TRUE)
      ```
      
      We used the following function:
      
      ```{r, code = inline_function_def(fit_main_model)}
      ```
    • Set Parameters Programmatically

      • Set Parameters

        ```{r}
        #| output: asis
        
        write_yaml_metadata_block(
          is_france = params$country == "france"
        )
        ```
      • Output

        ---
        is_france: true
        ---
      • Use parameter

        ::: {.content-visible when-meta="is_france"}
        ## Fun fact about France
        
        In 2025, France is the most visited country in the world, attracting over 89 million tourists annually!
        
        :::
    • Inspect document before rendering

      # Check if a document has parameters (uses quarto inspect internally)
      if (has_parameters("report.qmd")) {
        quarto_render("report.qmd", execute_params = list(year = 2025))
      }
    • Pass database credentials/password via user prompt (source)

      quarto::quarto_render(
        input = "results/initial-results.qmd",
        execute_params = list(db_password = rstudioapi::askForPassword())
      )
  • Include shortcode to copy/paste the content of another quarto document (Docs, Article)

    • Relative references (links, images, etc.) inside the included file resolve based on the directory of the main file not the included file

    • Need to appear by themselves in a line, and they need to be surrounded by empty lines. This means that you cannot use an include shortcode inside markdown syntax (such as an item in a bulleted list).

    • Use cases: block of text, code cells

    • Example: Text

      • Source Document (_snippets/state-intro.qmd)

        In this document, we cover facts that are unique to the state, like the state's population, its flower, and animal.
        • So text that we want to appear at the top of multiple documents
      • Main Document

        ---
        title: New York
        ---
        
        {{< include _snippets/state-intro.qmd >}}
        
        New York has a geographical size of 54,555, making it the 27th largest state with an estimated population size of 19.8 million.
        
        The state's flower is the Rose, as shown below:
        
        ![](images/ny/flower.png)
    • Example: Text with parameters

      • Source Document (_snippets/facts.qmd)

        {{< meta state >}} covers approximately {{< meta square-miles >}} making it the {{< meta size-rank >}} largest state in the United States. As of 2023, {{< meta state >}} has an approximate population of about {{< meta population >}}.
        • state, square-miles, size-rank, and population are parameters whose values will be set in the the main document.
      • Main Document

        ---
        title: New York
        state-abbr: ny
        state: New York
        size-rank: 27th
        square-miles: 54,555
        population: 19.8 million
        flower: Rose
        ---
        
        
        {{< include _snippets/facts.qmd >}}
        
        {{< meta state >}}'s official flower is the {{< meta flower >}}, pictured below:
        
        ![The official {{< meta state >}} state flower, the {{< meta flower >}}](../images/{{< meta state-abbr >}}/flower.png)
        • The text from the source document is transferred to the main document and the parameter values set in the yaml will be inserted into appropriate shortcode locations.

        • Meta variables are also used in image captions and file paths

    • Using External Quarto Files (Docs):

      {{< include file.qmd >}}
  • Iteration and Parameterization

    • Misc

      • Notes from

      • Might need to use fs::file_move to move processed reports to another folder.

        • You can also use Quarto Project and its _quarto.yml file to specify a directory

          project:
            output-dir: "Outputs"
          • If you’re publishing your document on GitHub Pages (but not using GitHub Actions to render the documents), then setting output-dir: "docs" will make for easier set up.
        • Helper function that moves rendered files with base R file maintenance functions

      • Check the number of pages generated is correct (source)

        purrr::walk(list.files("generated_reports/", full.names = TRUE),
                    function (x) {
                      pdf_length <- pdftools::pdf_length(x)
                      if (pdf_length != 6) {
                        print(paste0(x, " reports ERROR"))
                      } else {
                        print("All reports have correct number of pages")
                      }
                    })
      • Plot Bug During Iteration (source, github issue)

        • When using walk, plots get overwritten in the loop and either none show up or only the last one shows up in the document.

        • Solution: Set Embed Resources in YAML

          ---
          format:
            html:
              embed-resources: true
          ---
    • It involves having a “child” document as a template and running it repeatedly with different parameters

    • The “main” document includes the output from the child document

    • Rendering Options

      • CLI: e.g. quarto render polling-places-report.qmd -P state:'California'

      • {quarto}:

        quarto::quarto_render(
          input = here::here("polling-places-report.qmd"),
          execute_params = list(state = "California")
          # execute_params = yaml::yaml.load_file("params.yml")
        )
        • YAML files can be used to deliver parameter values
    • Example: Create a report for each parameter value. In each report, use the parameter value (e.g. state) to iterate through a template file that makes a tables (1 for each county) based on that value.

    • Main Report Document

      ---
      title: "Polling Places Report - `r params$state`"
      params:
        state: "California"
      ---
      
      ```{r}
      #| results: hide
      
      library(dplyr)
      
      counties <- polling_places |> 
        filter(state == params$state) |> 
        distinct(county_name) |> 
        pull()
      
      expanded_child <- 
        counties |> 
          purrr::map(\(county) {
            knitr::knit_expand("../_template.qmd", 
                               current_county = county))
            }|> 
          purrr::flatten()
      
      parsed_child <- knitr::knit_child(text = unlist(expanded_child))
      ```
      
      `{{r}} parsed_child`
      • The document that gets published, emailed, etc.
      • params specified in YAML
        • Value can also be used in the title of the document via inline R code
      • Each county is iterated through the child document (_template.qmd) via current_county variable and knit_expand
      • parsed_child is a list of the template file outputs.
      • Then, parsed_child is converted to a character vector by unlist and all the results are printed in the document by the inline R code
    • Child Document (i.e. Template)

      ### {{current_county}} COUNTY
      
      -   Total Polling Places: `{r} polling_places |> filter(state == params$state, county_name == "{{current_county}}") |> count()`
      -   Example Locations:
      
      ```{r}
      polling_places |> 
        filter(state == params$state, 
               county_name == "{{current_county}}") |> 
        head(6) |> 
        select(name, address.x) |> 
        kbl(format = "markdown")
      ```
      • Parameter value is used to get county data and create tables for each.
      • No YAML is necessary in child document
        • params values are automatically available through knitr::knit_expand that’s executed in the Main document
      • The county variable is utilized by the template file using the double curly braces, {{current_county}}
      • kbl outputs in markdown format so the table is correctly rendered in the Main document.
    • Rendering Script

      • Example

        polling_places <-
          readr::read_csv(here::here("data", "geocoded_polling_places.csv"))
        
        # create quarto::render arguments df
        polling_places_reports <-
          polling_places |>
          dplyr::distinct(state) |>
          dplyr::slice_head(n = 5) |>
          dplyr::mutate(
            output_format = "html",
            output_file = paste0(tolower(state),
                                 "-polling-places"),
            execute_params = purrr::map(state,
                                        \(state) list(state = state))
          ) |>
          # default output is html, so that variable not selected
          dplyr::select(output_file, execute_params) 
        
        # iterate through args and create reports
        purrr::pwalk(
          .l = polling_places_reports,
          .f = quarto::quarto_render,
          input = here::here("main_report_document.qmd"),
          .progress = TRUE
        )
        • Creates a report for each params value (e.g. state)
        • Generates a dataframe for each set of arguments to be fed to quarto::quarto_render.
      • Example

        gapminder_params <- expand.grid(
          years = unique(gapminder$year),
          continents = unique(gapminder$continent)
        )
        
        
        walk2(
          .x = gapminder_params$years,
          .y = gapminder_params$continents,
          .f = ~quarto_render(
            input = "example.qmd",
            output_file = glue("report_{.x}_{.y}_{Sys.Date()}.html"),
            execute_params = list(
              choose_year = .x,
              choose_continent = .y
            )
          )
        )

WebR

  • Set-Up

    • Install the extension alongside your blog post by running quarto add coatless/quarto-webr
    • Add the extension to your blog by adding filters: ["webr"] to your post’s frontmatter
    • Instead of {r} code chunks, use {webr-r} ones
  • Install CRAN packages on page load

    filters:
      - "webr"
    webr:
      packages:
      - "dplyr"
      - "tidyr"
      - "purrr"
      - "tibble"
      - "crayon"
    • Add to frontmatter
  • Install R-Universe Package

    ```{webr-r}
    #| context: setup
    webr::install("collateral", repos = c("https://jimjam-slam.r-universe.dev"))
    ```
    • R-Universe packages must be installed in code cells

Extensions

  • Resources
  • Commands
    • CLI

      • Extension Install: quarto add username/repository
      • List exensions in a project: quarto list extensions
      • Remove: quarto remove username/repository
      • Update: quarto update username/repository
    • R

      # Add an extension
      quarto_add_extension("quarto-journals/jss")
      
      # List installed extensions
      quarto_list_extensions()
      
      # Remove an extension
      quarto_remove_extension("jss")
  • Icons
  • animate (library) - CSS text animations
  • arrow - Add arrows to documents, slides, typst, etc. (curvature, color, head symbol, etc. set interactively)
  • bluesky-comments - When someone visits your [Quarto] web page, any replies to the linked post are pulled from Bluesky and shown directly in the page
  • closeread (video) - Scrollytelling
    • Rennie example (code, source)

      • Clean look with text and visuals separated
      • Shows how scrolling can zoom into different areas of a chart
  • custom-callout - Allows you to customize callouts through yaml settings instead of inside the callout code or through css/scss.
  • elevator (library)- Adds a back-to-the-top button at the bottom of the page. Can add a .mp3 to play a sound while the page returns to the top
  • diagram - Adds a collection of diagram styles to your documents and Reveal.js presentations.
  • marimo - Full-featured notebook. Similar to Jupyter but has reactive cells — changing the value of variable in a cell will change it in other cells. I think it might be like an Observable notebook for Python
  • nutshell - Opens a window that includes only the snippet you need, not the whole page. Plus, instead of being lost in a jungle of new tabs, your reader stays on one page, keeping their flow of reading
  • social-share - Add buttons to share articles on various social media platforms
  • svelte - Lets you seamlessly write and include Svelte components, like charts and other visuals, in your Quarto website and documents.
    • It’s like adding shiny inputs and charts with just some js code.
  • Quarto Theme Tweaker - A Positron/VS Code extension for live Sass theming of Quarto documents.
    • Sliders and color pickers bound to Sass variables let you tweak a rendered Quarto document and see the changes instantly, then write the values back into custom.scss.
  • toggle - Adds a button to your code blocks that shows or hides the output on demand.

Slides

  • Packages
    • {deckroadmap} - Adds PowerPoint-style roadmap footers to Quarto and R Markdown Reveal.js slides
  • Resources
  • If you want to use inline code in a reveal-js without any other R code chunks, make sure to specify engine: knitr in your YAML (source)
    • Issue can come up when working on a title slide, and not having any code chunks yet.