Interactive tables in Quarto

You can create complex data visualization with R and Quarto, but there may be times when you just want to show your table of data in a way that is useful to readers. There are a number of ways to format tables. This page provides a preview of what you can do with tables in Quarto.

If you want a nicely formatted static table, look at the gt package. The documentation for the package is very thorough and provides many examples.

A minimally interactive option is rmarkdown::paged_table(), which can be chosen as the default table output within the df-print option in Quarto’s YAML. But you can get even fancier with either the DT package or reactable.

Examples

Let’s show examples using the movements of two sibling groups at the end of the 16th century.

library(tidyverse)
library(DT)
library(reactable)
movements <- read_csv("https://raw.githubusercontent.com/jessesadler/vt5444s26/refs/heads/main/datasets/movements.csv")

Regular tibble output

movements
# A tibble: 74 × 3
   person                 place     date      
   <chr>                  <chr>     <date>    
 1 Andries van der Meulen Antwerp   1584-07-01
 2 Andries van der Meulen Bremen    1585-09-01
 3 Anna van der Meulen    Cologne   1584-07-01
 4 Anna van der Meulen    Bremen    1588-06-01
 5 Anna van der Meulen    Stade     1588-08-01
 6 Anna van der Meulen    Bremen    1592-03-01
 7 Sara van der Meulen    Antwerp   1584-07-01
 8 Sara van der Meulen    Bremen    1585-09-01
 9 Sara van der Meulen    Frankfurt 1586-03-01
10 Sara van der Meulen    Cologne   1586-05-01
# ℹ 64 more rows

RMarkdown paged

rmarkdown::paged_table(movements)

DT

datatable(movements)

reactable

reactable(movements)

reactable

The DT package provides a nice default with a search box and includes many options for styling the table. However, reactable takes this even further, and so that is the package we will concentrate on here.

Resources and examples

The below will show some examples to help get you started, but look at the documentation for the many options available to you.

Movements example

The below is a relatively simple example that adds a search box, increases the default page side, changes some visual aspects of the table, and provides capitalized header values.

movements <- movements |> 
  arrange(date) |> 
  mutate(date = paste(day(date), # Transform to use of words for date
                      month(date, label = TRUE, abbr = FALSE),
                      year(date)))


reactable(movements,
          defaultPageSize = 15,
          searchable = TRUE,
          bordered = TRUE,
          highlight = TRUE,
          columns = list(
            person = colDef(name = "Person"),
            place = colDef(name = "Place"),
            date = colDef(name = "Date")
            )
          )

You can get quite creative with reactable, including adding filtering widgets and a button to download the data among many other options.