Creating {gt} frequency tables with {ivo.table}

R
Statistics
Author

Måns Thulin

Published

October 9, 2025

ivo.table version 0.7 is now available on CRAN. It adds support for creating gt tables, meaning that you can now create great-looking frequency tables and crosstables in the gt format with a single line of code.

Creating gt crosstables

In a previous post, I described how to create and style flextable frequency tables using the ivo_table function. In this post, I’ll describe the new ivo_table_gt function.

To create a three-way contingency table for the penguins data, we select the variables we wish to tabulate and pipe them to ivo_table_gt as follows:

library(dplyr)
library(ivo.table)

penguins |> select(species, sex, island) |> ivo_table_gt()
species
Adelie Chinstrap Gentoo
female
Biscoe 22 0 58
Dream 27 34 0
Torgersen 24 0 0
male
Biscoe 22 0 61
Dream 28 34 0
Torgersen 23 0 0
(Missing)
Biscoe 0 0 5
Dream 1 0 0
Torgersen 5 0 0

We can easily add row and column sums:

penguins |>
  select(species, sex, island) |>
  ivo_table_gt(sums = c("cols", "rows"))
species
Total
Adelie Chinstrap Gentoo
female
Biscoe 22 0 58 80
Dream 27 34 0 61
Torgersen 24 0 0 24
Total 73 34 58 165
male
Biscoe 22 0 61 83
Dream 28 34 0 62
Torgersen 23 0 0 23
Total 73 34 61 168
(Missing)
Biscoe 0 0 5 5
Dream 1 0 0 1
Torgersen 5 0 0 5
Total 6 0 5 11

Because ivo_table_gt creates a gt object, we can change the style of the table using standard gt functions like tab_style:

library(gt)
penguins |>
  select(species, sex, island) |>
  ivo_table_gt(color = "red",
               font_name = "Courier") |> 
  tab_style(style = list(cell_text(weight = "bold")),
                locations = cells_stub())
species
Adelie Chinstrap Gentoo
female
Biscoe 22 0 58
Dream 27 34 0
Torgersen 24 0 0
male
Biscoe 22 0 61
Dream 28 34 0
Torgersen 23 0 0
(Missing)
Biscoe 0 0 5
Dream 1 0 0
Torgersen 5 0 0

The caption´ argument lets us add a caption.tab_style` can also be used to highlight cells of particular interest:

penguins |>
  select(species, sex, island) |>
  ivo_table_gt(caption = "A table with penguins in it") |> 
    tab_style(style = list(cell_fill(color = "darkgreen")),
              locations = cells_body(columns = 5, rows = 4))
A table with penguins in it
species
Adelie Chinstrap Gentoo
female
Biscoe 22 0 58
Dream 27 34 0
Torgersen 24 0 0
male
Biscoe 22 0 61
Dream 28 34 0
Torgersen 23 0 0
(Missing)
Biscoe 0 0 5
Dream 1 0 0
Torgersen 5 0 0

The best part

What I think makes using gt tables instead of flextable tables an appealing option is that we can paste them with ggplot objects using the patchwork package, like so:

library(ggplot2)
library(patchwork)

penguins_plot <- ggplot(penguins, aes(body_mass, fill = species)) +
                    geom_density(alpha = 0.7) +
                    theme(legend.position = "bottom")

penguins_table <- penguins |>
                    select(species, sex, island) |>
                    ivo_table_gt()

penguins_plot + penguins_table

This should be really useful for presentations and other situations where we don’t need the table to be in a text format.

ivo_table_gt was developed by Stefan Furne. Thanks Stefan!