rmarkdownquarto

Quarto PowerPoint slide with two plots side by side and descriptive text at the bottom of the slide?


How can I create a PowerPoint presentation with quarto, with two plots side by side, and include descriptive text at the bottom of each slide (like the one shown in screenshot)? The issue I have is that the text is appearing on the second slide instead of bottom of the plots on the same slide.

---
title: "iris Presentation"
format: pptx
---
parts of the code are from: https://github.com/quarto-dev/quarto-cli/discussions/2403 
```{r, include=FALSE}
library(tidyverse)

# Create histogram for each species
spec_name <- unique(iris$Species)

make_hist <- function(spec) {
  iris |> 
    filter(Species == spec) |> 
    ggplot(aes(x = Petal.Length)) +
    geom_histogram(bins = 10, fill = "steelblue", color = "white") +
    labs(title = paste("Petal Length Histogram -", spec))
}

list_hist <- map(spec_name, make_hist)

# Create a second set of plots (random scatter plots)
make_random_plot <- function() {
  tibble(x = rnorm(50), y = rnorm(50)) |> 
    ggplot(aes(x, y)) +
    geom_point(color = "darkorange") +
    labs(title = "Random Scatter Plot")
}

list_random <- map(spec_name, ~ make_random_plot())

# Combine into a data frame
df <- tibble(spec = spec_name, 
             plot1 = list_hist, 
             plot2 = list_random)
```

```{r}
#| output: asis
res <- pmap_chr(df, \(spec, plot1, plot2) {
  knitr::knit_child(text = c(
    paste0("## ", spec, " - Summary"),
    
    "```{r}",
    "#| echo: false",
    "#| layout-ncol: 2",
    "plot1",
    "plot2",
    "```",
    
    "",
    
    paste("This slide shows the distribution of Petal Length for", spec,
          "alongside a comparison scatter plot of random values.")
  ), envir = environment(), quiet = TRUE)
})
cat(res, sep = '\n')
```

Desired output:

fd


Solution

  • The issue is that quarto or more precisely pandoc supports only a limited number of slide layouts (For an overview of the supported layouts see the docs), i.e. to display two charts side by side there is the "Two Content" layout or the "Comparison" layout. However, there is no slide layout which allows to have two charts side by side and to have a text content beneath the charts.

    Accounting for these limitations, one option to achieve your desired result would be to create the content as one chart, i.e. in the code below I use patchwork to combine the charts and the annotation, where for the latter I use gridtext::textbox_grob. This is far from optimal as you can't edit the annotation in Powerpoint.

    ---
    title: "iris Presentation"
    format: 
      pptx:
        keep-md: true
    ---
    
    parts of the code are from: https://github.com/quarto-dev/quarto-cli/discussions/2403 
    
    ```{r, include=FALSE}
    library(tidyverse)
    library(patchwork)
    
    # Create histogram for each species
    spec_name <- unique(iris$Species)
    
    make_hist <- function(spec) {
      iris |>
        filter(Species == spec) |>
        ggplot(aes(x = Petal.Length)) +
        geom_histogram(bins = 10, fill = "steelblue", color = "white") +
        labs(title = paste("Petal Length Histogram -", spec))
    }
    
    list_hist <- map(spec_name, make_hist)
    
    # Create a second set of plots (random scatter plots)
    make_random_plot <- function() {
      tibble(x = rnorm(50), y = rnorm(50)) |>
        ggplot(aes(x, y)) +
        geom_point(color = "darkorange") +
        labs(title = "Random Scatter Plot")
    }
    
    list_random <- map(spec_name, ~ make_random_plot())
    
    # Combine into a data frame
    df <- tibble(
      spec = spec_name,
      plot1 = list_hist,
      plot2 = list_random
    )
    ```
    
    ```{r}
    #| output: asis
    res <- pmap_chr(df, \(spec, plot1, plot2) {
      annotation <- gridtext::textbox_grob(
        text = paste(
          "This slide shows the distribution of Petal Length for",
          spec,
          "alongside a comparison scatter plot of random values."
        ),
        gp = grid::gpar(fontsize = 24)
      )
      knitr::knit_child(text = c(
        paste0("## ", spec, " - Summary\n"),
        "```{r}",
        "#| echo: false",
        "(plot1 + plot2) / annotation +",
        "plot_layout(heights = c(2, 1))",
        "```"
      ), envir = environment(), quiet = TRUE)
    })
    cat(res, sep = "\n")
    ```
    

    enter image description here