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.




Sunday, the 5 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.

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

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

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

#| echo: false
#| output: asis
    "- `%s` (@tbl-%s)",
  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(
    "#| echo: false",
    sprintf("#| tbl-cap: %s", ispecies),
    sprintf("#| label: tbl-%s", ispecies),

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.