Interactive tables

Author

Greg Martin

📊 Creating Interactive Tables with the DT Package

The DT package in R makes it easy to create interactive tables that work inside websites, Quarto documents, and Shiny apps. These tables let users search, sort, filter, paginate, and even download the data, all through a web-based interface.

DT is a wrapper around the JavaScript DataTables library, but you don’t need to know any JavaScript — it works directly with your R data frames or tibbles.


🔧 Getting Started

Install and load the DT package:

Show the code
install.packages("DT")
library(DT)
1
Install the DT package if not already installed
2
Load the DT package for creating interactive tables

🧱 Basic Table Creation

Use the datatable() function to turn a data frame into an interactive table.

Show the code
datatable(mtcars)
1
Create basic interactive table from mtcars dataset

🔍 Adding Filters to Each Column

You can add filters to each column using the filter argument.

Show the code
mtcars %>% 
  select(1:4) %>% 
datatable(filter = "top")
1
Add column filters at the top of the table

📐 Controlling Page Size and Menu Options

Control how many rows appear on each page with pageLength, and give users a menu of page sizes using lengthMenu.

Show the code
mtcars %>% 
  select(1:4) %>% 
datatable(options = list(
          pageLength = 5,
          lengthMenu = c(5, 10, 20, 50)
          ))
1
Set initial display to 5 rows per page
2
Create dropdown menu with page length options

🏷️ Custom Column Names

Use the colnames argument to rename the columns.

Show the code
datatable(mtcars,
          colnames = c("Miles/Gallon", "Cylinders", "Displacement", "Horsepower",
                       "Rear Axle Ratio", "Weight", "1/4 Mile Time", 
                       "V/S", "Transmission", "Gears", "Carburetors"))
1
Replace default column names with descriptive labels

🎨 Adding Colour Bars to Cells

Colour bars make it easy to visually compare values.

Show the code
mtcars %>% 
  select(1:4) %>% 
datatable() %>%
  formatStyle(
    "mpg",
    background = styleColorBar(range(mtcars$mpg), "lightblue"),
    backgroundSize = "100% 90%",
    backgroundRepeat = "no-repeat"
  )
1
Apply styling to MPG column
2
Create colour bar but firstly defining the min and max range of values from the mpg column and then defining the colour as lightblue
3
Set bar width to 100% and height to 90% of cell
4
Prevent background pattern repetition. By default, backgrounds can “tile” or repeat if they are smaller than the cell.

✨ Using Extensions

Add interactive features with extensions.

Extension Features:

  • Buttons: adds export/copy buttons
  • ColReorder: lets users drag columns
  • FixedHeader: keeps headers visible while scrolling
  • Scroller: improves performance with large table
  • KeyTable: enables arrow-key navigation
Show the code
mtcars %>% 
  select(1:4) %>% 
datatable(extensions = c("Buttons", "ColReorder", "FixedHeader", "Scroller", "KeyTable"),
          options = list(
            dom = 'Bfrtip',
            buttons = c('copy', 'csv', 'excel', 'pdf', 'print'),
            colReorder = TRUE,
            fixedHeader = TRUE,
            scrollY = 300,
            scroller = TRUE,
            keys = TRUE
          ))
1
Load multiple DataTables extensions
2
Define table control elements layout
3
Add export/action buttons
4
Enable column reordering by dragging
5
Fix header position during scrolling
6
Set vertical scroll height to 300px
7
Enable smooth scrolling for large datasets
8
Activate keyboard navigation

Worked example

Show the code
library(gapminder)
library(dplyr)
library(DT)

gap_enhanced <- gapminder %>%
  filter(continent == "Europe") %>%
  mutate(
    year = as.factor(year),
    country_html = paste0("🌍", country)
  ) %>%
  mutate(country_html = as.factor(country_html)) %>% 
  select(country_html, year, lifeExp, pop, gdpPercap)

datatable(
  gap_enhanced,
  colnames = c("Country", "Year", "LifeExp", "Population", "GDP per capita"),
  escape = FALSE,
  extensions = c('Buttons', 'ColReorder', 'FixedHeader', 'Scroller', 'KeyTable'),
  options = list(
    dom = 'Bfrtip',
    buttons = c('copy', 'csv', 'excel', 'pdf', 'print'),
    colReorder = TRUE,
    fixedHeader = TRUE,
    scrollY = 400,
    scroller = TRUE,
    keys = TRUE,
    pageLength = 15,
    order = list(list(1, 'desc')),
    searchCols = list(NULL, list(search = "2007"), NULL, NULL, NULL)
  ),
  filter = 'top',
  rownames = FALSE,
  caption = '📊 Gapminder data for European countries — comparing life expectancy, population, and GDP per capita'
) %>%
  formatStyle(
    'lifeExp',
    background = styleColorBar(range(gap_enhanced$lifeExp), 'lightblue'),
    backgroundSize = '100% 90%',
    backgroundRepeat = 'no-repeat'
  ) %>%
  formatStyle(
    'pop',
    background = styleColorBar(range(gap_enhanced$pop), 'pink'),
    backgroundSize = '100% 90%',
    backgroundRepeat = 'no-repeat'
  ) %>%
  formatStyle(
    'gdpPercap',
    background = styleColorBar(range(gap_enhanced$gdpPercap), 'lightgreen'),
    backgroundSize = '100% 90%',
    backgroundRepeat = 'no-repeat'
  ) %>%
  formatRound(c('lifeExp', 'pop'), digits = c(1, 0)) %>%
  formatCurrency('gdpPercap', currency = '$', digits = 0)
1
Loads the gapminder package, which contains country-level statistics over time.
2
Loads dplyr, a package for data manipulation.
3
Loads DT, which lets you create interactive HTML tables in R.
4
Filters the dataset to include only European countries.
5
Converts the year column to a factor so it displays as a dropdown filter.
6
Creates a new column with a globe emoji and bolded country name using HTML.
7
Selects only the columns needed for the table.
8
Sets custom column headings to be more readable.
9
Enables HTML rendering inside the table (for emojis and bold text).
10
Adds five extensions for interactivity: buttons, drag-and-drop, fixed headers, scrollable display, and keyboard navigation.
11
Controls layout of the table. B = buttons, f = filtering, r =processing display, t = Table, i = information summary, p = pagination controls
12
Adds export and print options.
13
Sets the vertical scroll height for the table to 400 pixels.
14
Optimizes performance by only rendering visible rows.
15
Enables navigation through the table using the keyboard.
16
Sorts the table by year in descending order.
17
Pre-filters the Year column to default to 2007.
18
Places filter boxes at the top of each column.
19
Applies a light blue color bar to the lifeExp column.
20
Applies a pink color bar to the pop column.
21
Applies a light green color bar to the gdpPercap column.