Quarto Q&A: How to have labels and captions for an unknown number of tables?

A small example of how to automatically have labels and captions for an unknown number of tables in Quarto, using knitr and R.

Quarto
Q&A
R
knitr
Author

Mickaël CANOUIL

Published

Sunday, the 5th of March, 2023

I decided to start small blog posts with answers/solutions to questions I have seen and answered on Twitter, Mastodon, and Quarto GitHub Issues & Discussions.

Screenshot of an html rendered by Quarto. it starts with a sentence saying below are several tables by species of penguins, followed by an item list showing the species and their respective cross-reference to the tables. Tables are simply on top of each other after the item list.

1 The Question/Problem

Suppose, in a #QuartoPub document, using #rStats I have a list of length G, each item in this list is a flextable - I need to use flextable as opposed to kable, to allow for output to docx. G is unknown apriori, but will be at least 1.

Is there any way to create a sequence of tables with associated labels and captions that could be worked out dynamically/parsed? Manually, this can be done really easily (creating new labels etc) and knowing when to stop, but is there a way of automating this?

Source: https://mastodon.ie/@DToher/109915736491084825

2 The Answer/Solution

The trick is, within a code cell with output: asis, to use knitr::knit_child() to create code cells with label, caption (tbl-cap), or whatever option you might want or need.

---
format: html
---

```{r}
#| include: false
for (ipkg in c("palmerpenguins", "gt", "dplyr")) {
  if (!require(ipkg, character.only = TRUE)) {
    install.packages(ipkg)
    library(ipkg, character.only = TRUE)
  }
}
```

Below are tables of the first six rows of the Palmer penguins dataset by species:

```{r}
#| echo: false
#| output: asis
cat(
  sprintf(
    "- `%s` (@tbl-%s)",
    levels(penguins[["species"]]),
    levels(penguins[["species"]])
  ),
  sep = "\n"
)

for (ispecies in levels(penguins[["species"]])) {
  tab <- penguins |>
    filter(species %in% ispecies) |>
    select(-species) |>
    head() |>
    gt() |>
    tab_header(title = ispecies)
  cat(sep = "\n", knitr::knit_child(quiet = TRUE, text = c(
    "```{r}",
    "#| echo: false",
    sprintf("#| tbl-cap: %s", ispecies),
    sprintf("#| label: tbl-%s", ispecies),
    "tab",
    "```"
  )))
}
```

Screenshot of an html rendered by Quarto. it starts with a sentence saying below are several tables by species of penguins, followed by an item list showing the species and their respective cross-reference to the tables. Tables are simply on top of each other after the item list.

3 References

References: - https://bookdown.org/yihui/rmarkdown-cookbook/child-document.html - https://bookdown.org/yihui/rmarkdown-cookbook/knit-expand.html - https://bookdown.org/yihui/rmarkdown-cookbook/results-asis.html

4 Examples