Skip to content

Instantly share code, notes, and snippets.

@andrewheiss
Last active October 30, 2024 15:26
Show Gist options
  • Save andrewheiss/88252d55878ab01166db7e7ee605f0a6 to your computer and use it in GitHub Desktop.
Save andrewheiss/88252d55878ab01166db7e7ee605f0a6 to your computer and use it in GitHub Desktop.
---
title: Panel tabset from list of plots
---
```{r}
#| warning: false
#| message: false
library(tidyverse)
library(glue)
# Make some plots
p1 <- ggplot(mpg, aes(x = cyl, y = hwy, color = drv)) +
geom_point()
p2 <- ggplot(mpg, aes(x = hwy, fill = drv)) +
geom_density()
p3 <- ggplot(mpg, aes(x = displ, y = hwy, color = drv)) +
geom_point()
# I find it easiest to work with all these things in a data frame, but it's not necessary
output_stuff <- tribble(
~panel_title, ~plot,
"Plot 1", p1,
"Plot 2", p2,
"Plot 3", p3
)
```
The plots are all in this `output_stuff$plot` list:
```{r}
output_stuff$plot[[3]]
```
For a tabset, the markdown needs to look like this:
````default
::: {.panel-tabset}
### Title
```{{r}}
output_stuff$plot[[1]]
```
### Another title
```{{r}}
output_stuff$plot[[2]]
```
:::
````
So we can build each of these panels in the data frame:
```{r}
build_panel <- function(panel_title, plot_index) {
output <- glue("
### <<panel_title>>
```{r}
#| echo: false
output_stuff$plot[[<<plot_index>>]]
```", .open = "<<", .close = ">>")
# ↑ It's best to override glue's {} delimiters because of the ```{r} chunk
output
}
output_with_markdown <- output_stuff |>
mutate(row = row_number()) |>
# We could use map2_chr(), but I like using pmap() just in case I need to
# expand it beyond 2 things
mutate(markdown = pmap_chr(
lst(panel_title, row),
\(panel_title, row) build_panel(panel_title, plot_index = row)
))
```
Now we have a markdown panel for each plot:
```{r}
cat(output_with_markdown$markdown[[1]])
```
```{r}
# We can collapse all these panels into one big character object, wrapped in Quarto's special .panel-tabset div
final_markdown <- paste0(
"::: {.panel-tabset}\n\n",
paste0(output_with_markdown$markdown, "\n", collapse = "\n"),
"\n:::"
)
```
Check it out!
```{r}
cat(final_markdown)
```
However, this won't render/knit properly, even if we add `results="asis"` to the chunk options.
But we can feed it to `knitr::knit()` in an inline chunk:
```r
# This, but in an inline chunk
knitr::knit(text = final_markdown)
```
`r knitr::knit(text = final_markdown)`
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment