How to render multiple ggplot plots into RevealJS look and interactivity?

Hi everyone,

I'm trying to find the best way to take an R script that generates multiple plots and render it as a Quarto RevealJS presentation where each set of plots gets its own slide.

My current script loops through a list of response variables and, for each one, creates a histogram and a Q-Q plot. In a standard HTML document, I can use patchwork to combine them and print them one after another, which works great.

Here is a reproducible example of my plotting code:

# Load libraries
library(ggplot2)
library(tidyverse)
library(patchwork)

# Create some fake data
set.seed(123)
df <- tibble(
  response_1 = rnorm(50),
  response_2 = rgamma(50, shape = 2),
  response_3 = runif(50)
)
response_var <- c('response_1', 'response_2', 'response_3')

# Loop to generate and print plots
for (var in response_var) {
  
  # 1. Histogram
  hist_plot <- ggplot(df, aes(x = .data[[var]])) +
    geom_histogram(bins = 10, fill = "steelblue", color = "black") +
    theme_minimal()
  
  # 2. QQ Plot
  qq_plot <- ggplot(df, aes(sample = .data[[var]])) +
    stat_qq() +
    stat_qq_line() +
    theme_minimal()
  
  # Combine and print
  combined_plot <- (hist_plot + qq_plot) + 
    plot_annotation(title = paste("Diagnostic Plots for", var))
  
  print(combined_plot)
}

My goal is to have the combined plot for response_1 on one slide, the plot for response_2 on the next slide, and so on. Basically, the look is like in here Revealjs – Quarto. But the content of each slide is in the .qmd in ggplot2 script format.

So when rendered, the .qmd processed the ggplot first, then the generated images were shown in that gallery RevealJS look.

Thanks in advance for any advice or examples!

Could you set the chunk to output: β€˜asis’ and then add a command like

cat(β€˜## Slide title \n\n’)

before the plot printing call in your for loop? That should print a new slide marker before each plot as raw markdown and render accordingly.

(Typed on a phone, please mind quotation marks if copy pasting!)

Another solution, less sophisticated than mthieu's but that may give you more control:

  1. Make combined_plot a list of length length(response_var) before your loop.
  2. Assign each combined plot to the corresponding element in combined_plot, i e., combined_plot[var] on the left side of β€Ή-.
  3. Index each element in combined_plot for convenience in each slide, e.g. print(combined_plot[1]).

Hope this is helpful!

P.S.: Also typed on phone, and untested sorry :slight_smile:

@mthieu is spot-on on combining output: asis with cat(). Here's what slides.qmd could look like, combined with @DaniMori's idea to keep the plot creation and plot printing separate:

---
title: "Untitled"
format: revealjs
---

```{r}
# Load libraries
library(ggplot2)
library(tidyverse)
library(patchwork)

# Create some fake data
set.seed(123)
df <- tibble(
  response_1 = rnorm(50),
  response_2 = rgamma(50, shape = 2),
  response_3 = runif(50)
)
response_var <- c('response_1', 'response_2', 'response_3')
combined_plot <- vector("list", length(response_var)) |> setNames(response_var)

# Loop to generate and print plots
for (var in response_var) {
  
  # 1. Histogram
  hist_plot <- ggplot(df, aes(x = .data[[var]])) +
    geom_histogram(bins = 10, fill = "steelblue", color = "black") +
    theme_minimal()
  
  # 2. QQ Plot
  qq_plot <- ggplot(df, aes(sample = .data[[var]])) +
    stat_qq() +
    stat_qq_line() +
    theme_minimal()
  
  # Combine and print
  combined_plot[[var]] <- (hist_plot + qq_plot) + 
    plot_annotation(title = paste("Diagnostic Plots for", var))
}
```

```{r}
#| output: asis

for (var in response_var) {
  cat("\n\n## Diagnostic Plots for", var, "\n\n")
  print(combined_plot[[var]])
}
```
1 Like