gt cookbook - advanced

A cookbook of advanced examples with extending {gt}
Author

Tom Mock

Introduction

This cookbook attempts to walk through many of the advanced applications for gt, and provide useful commentary around the use of the various gt functions. The full gt documentation has other more succinct examples and full function arguments.

For more introductory use cases, make sure to check out the {gt} Cookbook

Many of these examples rely on some working knowledge of:

  • HTML
  • CSS
  • Functional Programming
  • purrr and or apply

I am a big fan the Mozilla MDN Web Docs for learning more about how to code up the web with front-end developement. They have sections on general reference material, Tutorials, and Developer Guides.

As far as functional programming and purrr, I suggest checking out R4DS Functions Chapter, R4DS Iteration chapter, and Advanced R’s Function chapter, and lastly the Learn to purrr guide by Rebecca Barter.

Custom CSS

For more control over styling, you can add custom class names to the table and apply your own CSS. Note that this can require more effort than the built in gt functions, but also allows some things that aren’t possible by the functions align (like hover highlighting!).

 exibble %>%
  dplyr::select(num, currency) %>%
  gt(id = "one") %>% # need to name the table so that you can apply CSS
  fmt_currency(
    columns = vars(currency),
    currency = "HKD"
  ) %>%
  fmt_scientific(
    columns = vars(num)
  ) %>%
  opt_css(
    css = "
    #one .gt_table {
      background-color: lightgrey;
    }
    #one .gt_row {
      padding: 20px 30px;
    }
    #one tr:hover {
    background-color: #f5f8ff;
    }
    #one .gt_col_heading {
      text-align: center !important;
    }
    "
  )
Warning: `columns = vars(...)` has been deprecated in gt 0.3.0:
* please use `columns = c(...)` instead

Warning: `columns = vars(...)` has been deprecated in gt 0.3.0:
* please use `columns = c(...)` instead

Warning: `columns = vars(...)` has been deprecated in gt 0.3.0:
* please use `columns = c(...)` instead

Warning: `columns = vars(...)` has been deprecated in gt 0.3.0:
* please use `columns = c(...)` instead
num currency
1.11 × 10−1 HK$49.95
2.22 HK$17.95
3.33 × 101 HK$1.39
4.44 × 102 HK$65,100.00
5.55 × 103 HK$1,325.81
NA HK$13.26
7.77 × 105 NA
8.88 × 106 HK$0.44

The examples here embed CSS for demonstration, but it’s often better to put CSS in an external style sheet. You can learn more about adding custom CSS to R Markdown documents here, or to Shiny apps here.

Parse arbitrary HTML

Because gt supports HTML, you can also optionally “create” HTML strings prior to passing them into gt proper.

color_span <- function(x){paste0("<span style='color: ", x, ";'>", x, "</span>")}

data.frame(
  count = c(1L, 2L, 3L, 4L, 5L),
  weight_g = c(150.65, 149.65, 171.28, 142.58, 139.04),
  color = c("green", "yellow", "yellow", "green", "yellow")
) %>% 
  mutate(color = color_span(color)) %>% 
  mutate(color = purrr::map(color, gt::html)) %>% 
  gt() 
count weight_g color
1 150.65 green
2 149.65 yellow
3 171.28 yellow
4 142.58 green
5 139.04 yellow

Embed URLs

You can also use things like htmltools or glue to arbitrarily build HTML content like hyperlinks.

library(htmltools)
ex_sites <- data.frame(
  Address = c("https://google.com", "https://yahoo.com", "https://duckduckgo.com"),
  Site = c("Google", "Yahoo", "DuckDuckGo")
)
gt(ex_sites) %>% 
  text_transform(
    locations = cells_body(columns = vars(Address)),
    fn = function(x) {
    purrr::map(x,  ~htmltools::tags$a(href = .x, target = "_blank", .x))
      }
  ) %>% 
  text_transform(
    locations = cells_body(columns = vars(Site)),
    fn = function(x) {
    purrr::map2(
      .x = x, .y = ex_sites$Address, 
      .f = ~glue::glue('<a href="{.y}" target="_blank">{.x}</a>'))
      }
  )
Warning: `columns = vars(...)` has been deprecated in gt 0.3.0:
* please use `columns = c(...)` instead

Warning: `columns = vars(...)` has been deprecated in gt 0.3.0:
* please use `columns = c(...)` instead
Address Site
https://google.com Google
https://yahoo.com Yahoo
https://duckduckgo.com DuckDuckGo

Embed data

While gt tables can be beautiful, it’s often best to also include the raw data for download. You can see how to do this with Markdown or HTML thanks to Bob Rudis’ example.

write.csv2(mtcars, "./file.csv")

encoded <- readLines("./file.csv") %>% 
  paste0(collapse="\n") %>% 
  openssl::base64_encode() -> encoded

The raw markdown could be embedded in a Shiny app or RMarkdown document as seen below.

[Download CSV](data:text/csv;base64,IiI7Im1wZyI7ImN5bCI7ImRpc3AiOyJocCI7ImRyYXQiOyJ3dCI7InFzZWMiOyJ2cyI7ImFtIjsiZ2VhciI7ImNhcmIiCiJNYXpkYSBSWDQiOzIxOzY7MTYwOzExMDszLDk7Miw2MjsxNiw0NjswOzE7NDs0CiJNYXpkYSBSWDQgV2FnIjsyMTs2OzE2MDsxMTA7Myw5OzIsODc1OzE3LDAyOzA7MTs0OzQKIkRhdHN1biA3MTAiOzIyLDg7NDsxMDg7OTM7Myw4NTsyLDMyOzE4LDYxOzE7MTs0OzEKIkhvcm5ldCA0IERyaXZlIjsyMSw0OzY7MjU4OzExMDszLDA4OzMsMjE1OzE5LDQ0OzE7MDszOzEKIkhvcm5ldCBTcG9ydGFib3V0IjsxOCw3Ozg7MzYwOzE3NTszLDE1OzMsNDQ7MTcsMDI7MDswOzM7MgoiVmFsaWFudCI7MTgsMTs2OzIyNTsxMDU7Miw3NjszLDQ2OzIwLDIyOzE7MDszOzEKIkR1c3RlciAzNjAiOzE0LDM7ODszNjA7MjQ1OzMsMjE7Myw1NzsxNSw4NDswOzA7Mzs0CiJNZXJjIDI0MEQiOzI0LDQ7NDsxNDYsNzs2MjszLDY5OzMsMTk7MjA7MTswOzQ7MgoiTWVyYyAyMzAiOzIyLDg7NDsxNDAsODs5NTszLDkyOzMsMTU7MjIsOTsxOzA7NDsyCiJNZXJjIDI4MCI7MTksMjs2OzE2Nyw2OzEyMzszLDkyOzMsNDQ7MTgsMzsxOzA7NDs0CiJNZXJjIDI4MEMiOzE3LDg7NjsxNjcsNjsxMjM7Myw5MjszLDQ0OzE4LDk7MTswOzQ7NAoiTWVyYyA0NTBTRSI7MTYsNDs4OzI3NSw4OzE4MDszLDA3OzQsMDc7MTcsNDswOzA7MzszCiJNZXJjIDQ1MFNMIjsxNywzOzg7Mjc1LDg7MTgwOzMsMDc7Myw3MzsxNyw2OzA7MDszOzMKIk1lcmMgNDUwU0xDIjsxNSwyOzg7Mjc1LDg7MTgwOzMsMDc7Myw3ODsxODswOzA7MzszCiJDYWRpbGxhYyBGbGVldHdvb2QiOzEwLDQ7ODs0NzI7MjA1OzIsOTM7NSwyNTsxNyw5ODswOzA7Mzs0CiJMaW5jb2xuIENvbnRpbmVudGFsIjsxMCw0Ozg7NDYwOzIxNTszOzUsNDI0OzE3LDgyOzA7MDszOzQKIkNocnlzbGVyIEltcGVyaWFsIjsxNCw3Ozg7NDQwOzIzMDszLDIzOzUsMzQ1OzE3LDQyOzA7MDszOzQKIkZpYXQgMTI4IjszMiw0OzQ7NzgsNzs2Njs0LDA4OzIsMjsxOSw0NzsxOzE7NDsxCiJIb25kYSBDaXZpYyI7MzAsNDs0Ozc1LDc7NTI7NCw5MzsxLDYxNTsxOCw1MjsxOzE7NDsyCiJUb3lvdGEgQ29yb2xsYSI7MzMsOTs0OzcxLDE7NjU7NCwyMjsxLDgzNTsxOSw5OzE7MTs0OzEKIlRveW90YSBDb3JvbmEiOzIxLDU7NDsxMjAsMTs5NzszLDc7Miw0NjU7MjAsMDE7MTswOzM7MQoiRG9kZ2UgQ2hhbGxlbmdlciI7MTUsNTs4OzMxODsxNTA7Miw3NjszLDUyOzE2LDg3OzA7MDszOzIKIkFNQyBKYXZlbGluIjsxNSwyOzg7MzA0OzE1MDszLDE1OzMsNDM1OzE3LDM7MDswOzM7MgoiQ2FtYXJvIFoyOCI7MTMsMzs4OzM1MDsyNDU7Myw3MzszLDg0OzE1LDQxOzA7MDszOzQKIlBvbnRpYWMgRmlyZWJpcmQiOzE5LDI7ODs0MDA7MTc1OzMsMDg7Myw4NDU7MTcsMDU7MDswOzM7MgoiRmlhdCBYMS05IjsyNywzOzQ7Nzk7NjY7NCwwODsxLDkzNTsxOCw5OzE7MTs0OzEKIlBvcnNjaGUgOTE0LTIiOzI2OzQ7MTIwLDM7OTE7NCw0MzsyLDE0OzE2LDc7MDsxOzU7MgoiTG90dXMgRXVyb3BhIjszMCw0OzQ7OTUsMTsxMTM7Myw3NzsxLDUxMzsxNiw5OzE7MTs1OzIKIkZvcmQgUGFudGVyYSBMIjsxNSw4Ozg7MzUxOzI2NDs0LDIyOzMsMTc7MTQsNTswOzE7NTs0CiJGZXJyYXJpIERpbm8iOzE5LDc7NjsxNDU7MTc1OzMsNjI7Miw3NzsxNSw1OzA7MTs1OzYKIk1hc2VyYXRpIEJvcmEiOzE1Ozg7MzAxOzMzNTszLDU0OzMsNTc7MTQsNjswOzE7NTs4CiJWb2x2byAxNDJFIjsyMSw0OzQ7MTIxOzEwOTs0LDExOzIsNzg7MTgsNjsxOzE7NDsy)

Or you can embed it as HTML using the html_csv object as seen above/below.

html_encode <- sprintf('data:text/csv;base64,%s', encoded)
html_csv <- glue::glue(
  "<a download='mtcars.csv' href='{html_encode}'>CSV Download</a>"
  )

head(mtcars) %>% 
  gt() %>% 
  tab_source_note(html(html_csv))
mpg cyl disp hp drat wt qsec vs am gear carb
21.0 6 160 110 3.90 2.620 16.46 0 1 4 4
21.0 6 160 110 3.90 2.875 17.02 0 1 4 4
22.8 4 108 93 3.85 2.320 18.61 1 1 4 1
21.4 6 258 110 3.08 3.215 19.44 1 0 3 1
18.7 8 360 175 3.15 3.440 17.02 0 0 3 2
18.1 6 225 105 2.76 3.460 20.22 1 0 3 1
CSV Download


You can make this process a bit easier with the downloadthis R package. It supports csv, Excel and even .rds files! It also takes care of the “download button”, and supports Bootstrap button styles. H/t to Kyle Cuilla for the suggestion and Jonathan Regenstein for the ask of how to do this.

library(downloadthis)

head(mtcars) %>%
  gt() %>%
  tab_source_note(
    mtcars %>%
      download_this(
        output_name = "mtcars",
        output_extension = ".csv", # CSV output
        button_label = "Download csv",
        button_type = "default",
      )
  )
mpg cyl disp hp drat wt qsec vs am gear carb
21.0 6 160 110 3.90 2.620 16.46 0 1 4 4
21.0 6 160 110 3.90 2.875 17.02 0 1 4 4
22.8 4 108 93 3.85 2.320 18.61 1 1 4 1
21.4 6 258 110 3.08 3.215 19.44 1 0 3 1
18.7 8 360 175 3.15 3.440 17.02 0 0 3 2
18.1 6 225 105 2.76 3.460 20.22 1 0 3 1


You can specify the file/output extension, and the button type to alter the appearance. Note that the code works inline as seen above, or defined in an external object as seen below.

attach_excel <- mtcars %>%
  download_this(
    output_name = "mtcars",
    output_extension = ".xlsx", # Excel file type
    button_label = "Download Excel",
    button_type = "primary", # change button type
  )

head(mtcars) %>%
  gt() %>%
  tab_source_note(attach_excel)
mpg cyl disp hp drat wt qsec vs am gear carb
21.0 6 160 110 3.90 2.620 16.46 0 1 4 4
21.0 6 160 110 3.90 2.875 17.02 0 1 4 4
22.8 4 108 93 3.85 2.320 18.61 1 1 4 1
21.4 6 258 110 3.08 3.215 19.44 1 0 3 1
18.7 8 360 175 3.15 3.440 17.02 0 0 3 2
18.1 6 225 105 2.76 3.460 20.22 1 0 3 1


You can continue and go one step farther by adding custom styling CSS to the table to affect the button style.

attach_excel <- mtcars %>%
  download_this(
    output_name = "mtcars",
    output_extension = ".xlsx", # Excel file type
    button_label = "Download Excel",
    class = "buttonExcel"
  )

head(mtcars) %>%
  gt() %>%
  opt_css(
    css = "
    .buttonExcel{
    font-size: 12px;
    color: #fff;
    background-color: black;
    border-color: black;
    font-weight: bold;
    border-radius: 10px;
    padding: 4px;
    }
    
    .buttonExcel:hover,
    .buttonExcel:active,
    .buttonExcel:focus,
    .buttonExcel.active {
    background: grey;
    color: #ffffff;
    border-color: grey;
    }
    "
  ) %>% 
  tab_source_note(attach_excel)
mpg cyl disp hp drat wt qsec vs am gear carb
21.0 6 160 110 3.90 2.620 16.46 0 1 4 4
21.0 6 160 110 3.90 2.875 17.02 0 1 4 4
22.8 4 108 93 3.85 2.320 18.61 1 1 4 1
21.4 6 258 110 3.08 3.215 19.44 1 0 3 1
18.7 8 360 175 3.15 3.440 17.02 0 0 3 2
18.1 6 225 105 2.76 3.460 20.22 1 0 3 1

Combine and stack

Combine text into div containers and then “stack” the text on top of each other with alternating color.

stack_function <- function(x){
  
  name <- sub(x = x, pattern = " .*$", replacement = "")
  model <- sub(x = x, pattern = ".*? ", replacement = "")

  
  glue::glue(
    "<div style='line-height:10px'>
    <span style='font-weight:bold;font-variant:small-caps;font-size:14px'>
    {name}</div>
    <div style='line-height:12px'>
    <span style ='font-weight:bold;color:grey;font-size:10px'>
    {model}</span></div>"
  )
    }

head(gtcars) %>% 
  dplyr::select(mfr, model, year, trim, hp) %>%
  gt() %>% 
  cols_merge(
    columns = vars(mfr, model)
  ) %>% 
  text_transform(
    locations = cells_body(
      columns = vars(mfr)
    ),
    fn = stack_function
  ) %>% 
  tab_options(
    data_row.padding = px(5),
  )
Warning: `columns = vars(...)` has been deprecated in gt 0.3.0:
* please use `columns = c(...)` instead

Warning: `columns = vars(...)` has been deprecated in gt 0.3.0:
* please use `columns = c(...)` instead
mfr year trim hp
Ford
GT
2017 Base Coupe 647
Ferrari
458 Speciale
2015 Base Coupe 597
Ferrari
458 Spider
2015 Base 562
Ferrari
458 Italia
2014 Base Coupe 562
Ferrari
488 GTB
2016 Base Coupe 661
Ferrari
California
2015 Base Convertible 553

Align symbol on first row only

We can align text on the first row only even with a suffix (ie symbol at the end). This can be done with just gt, but it’s a bit verbose.

This example applies a percent label to the hp_pct column and properly maintains the decimal place alignment.

head(gtcars) %>%
  mutate(hp_pct = (hp/max(hp) * 100)) %>% 
  dplyr::select(mfr, model, year, trim, hp, hp_pct) %>%
  gt() %>%
  # use a mono-spaced font
  tab_style(
    style = cell_text(font = google_font("Fira Mono")),
    locations = cells_body(columns = vars(hp_pct))
    ) %>% 
  # align the column of interst to right
  cols_align(align = "right", columns = vars(hp_pct)) %>% 
  # round and transform the first row to percent
  text_transform(
    locations = cells_body(vars(hp_pct), rows = 1),
    fn = function(x){ 
      fmt_val <- format(as.double(x), nsmall = 1, digits = 1)
      paste0(fmt_val, "%") %>% gt::html()}
  ) %>% 
  text_transform(
    locations = cells_body(vars(hp_pct), rows = 2:6),
    fn = function(x){ 
      # round remaining rows, add a non-breaking space
     fmt_val <- format(as.double(x), nsmall = 1, digits = 1)
     lapply(fmt_val, function(x) paste0(x, '&nbsp') %>% gt::html())
  })
Warning: `columns = vars(...)` has been deprecated in gt 0.3.0:
* please use `columns = c(...)` instead

Warning: `columns = vars(...)` has been deprecated in gt 0.3.0:
* please use `columns = c(...)` instead

Warning: `columns = vars(...)` has been deprecated in gt 0.3.0:
* please use `columns = c(...)` instead

Warning: `columns = vars(...)` has been deprecated in gt 0.3.0:
* please use `columns = c(...)` instead
mfr model year trim hp hp_pct
Ford GT 2017 Base Coupe 647 97.9%
Ferrari 458 Speciale 2015 Base Coupe 597 90.3&nbsp
Ferrari 458 Spider 2015 Base 562 85.0&nbsp
Ferrari 458 Italia 2014 Base Coupe 562 85.0&nbsp
Ferrari 488 GTB 2016 Base Coupe 661 100.0&nbsp
Ferrari California 2015 Base Convertible 553 83.7&nbsp

We can do the same thing with a custom gt function that we’ll call fmt_symbol_first().

fmt_symbol_first <- function(
  gt_data,
  column = NULL,        # column of interest to apply to
  symbol = NULL,        # symbol to add, optionally
  suffix = "",          # suffix to add, optionally
  decimals = NULL,      # number of decimal places to round to
  last_row_n,           # what's the last row in data?
  symbol_first = FALSE  # symbol before or after suffix?
) {
  
  # Test and error out if mandatory columns are missing
  stopifnot("`symbol_first` argument must be a logical" = is.logical(symbol_first))
  stopifnot("`last_row_n` argument must be specified and numeric" = is.numeric(last_row_n))
  stopifnot("Input must be a gt table" = class(gt_data)[[1]] == "gt_tbl")

  # needs to type convert to double to play nicely with decimals and rounding
  # as it's converted to character by gt::text_transform
  add_to_first <- function(x, suff = suffix, symb = symbol) {
    if (!is.null(decimals)) {
      x <- suppressWarnings(as.double(x))
      fmt_val <- format(x = x, nsmall = decimals, digits = decimals)
    } else {
      fmt_val <- x
    }

    # combine the value, passed suffix, symbol -> html
    if (isTRUE(symbol_first)) {
      paste0(fmt_val, symb, suff) %>% gt::html()
    } else {
      paste0(fmt_val, suff, symb) %>% gt::html()
    }
  }

  # repeat non-breaking space for combined length of suffix + symbol
  # logic is based on is a NULL passed or not
  if (!is.null(symbol) | !identical(as.character(symbol), character(0))) {
    suffix <- ifelse(identical(as.character(suffix), character(0)), "", suffix)
    length_nbsp <- c("&nbsp", rep("&nbsp", nchar(suffix))) %>%
      paste0(collapse = "")
  } else {
    suffix <- ifelse(identical(as.character(suffix), character(0)), "", suffix)
    length_nbsp <- rep("&nbsp", nchar(suffix)) %>%
      paste0(collapse = "")
  }

  # affect rows OTHER than the first row
  add_to_remainder <- function(x, length = length_nbsp) {
    if (!is.null(decimals)) {
      # if decimal not null, convert to double
      x <- suppressWarnings(as.double(x))
      # then round and format ALL to force specific decimals
      fmt_val <- format(x = x, nsmall = decimals, digits = decimals)
    } else {
      fmt_val <- x
    }
    paste0(fmt_val, length) %>% lapply(FUN = gt::html)
  }

  # pass gt object
  # align right to make sure the spacing is meaningful
  gt_data %>%
    cols_align(align = "right", columns = vars({{ column }})) %>%
    # convert to mono-font for column of interest
    tab_style(
      style = cell_text(font = google_font("Fira Mono")),
      locations = cells_body(columns = vars({{ column }}))
    ) %>%
    # transform first rows
    text_transform(
      locations = cells_body(vars({{ column }}), rows = 1),
      fn = add_to_first
    ) %>%
    # transform remaining rows
    text_transform(
      locations = cells_body(vars({{ column }}), rows = 2:last_row_n),
      fn = add_to_remainder
    )
}

Apply the custom function.

We can then use the function as a one-liner, and format just that column of interest.

head(gtcars) %>%
  mutate(hp_pct = (hp/max(hp) * 100)) %>% 
  dplyr::select(mfr, model, year, trim, hp, hp_pct) %>%
  gt() %>% 
  opt_table_lines() %>% 
  fmt_symbol_first(column = hp_pct, decimals = 1, suffix = "%", last_row_n = 6)
Warning: `columns = vars(...)` has been deprecated in gt 0.3.0:
* please use `columns = c(...)` instead

Warning: `columns = vars(...)` has been deprecated in gt 0.3.0:
* please use `columns = c(...)` instead

Warning: `columns = vars(...)` has been deprecated in gt 0.3.0:
* please use `columns = c(...)` instead

Warning: `columns = vars(...)` has been deprecated in gt 0.3.0:
* please use `columns = c(...)` instead
mfr model year trim hp hp_pct
Ford GT 2017 Base Coupe 647 97.9%
Ferrari 458 Speciale 2015 Base Coupe 597 90.3&nbsp
Ferrari 458 Spider 2015 Base 562 85.0&nbsp
Ferrari 458 Italia 2014 Base Coupe 562 85.0&nbsp
Ferrari 488 GTB 2016 Base Coupe 661 100.0&nbsp
Ferrari California 2015 Base Convertible 553 83.7&nbsp

Sparkline plots

We can embed sparkline plots with some help from the kableExtra package.

mtcars %>%
  group_by(cyl) %>%
  summarize(mpg_data = list(mpg), .groups = "drop") %>%
  gt() %>%
  text_transform(
    locations = cells_body(columns = vars(mpg_data)),
    fn = function(x) {
      data_in <- purrr::pluck(., "_data", "mpg_data")
      plot <- purrr::map(
        data_in, ~ kableExtra::spec_plot(
          .x, ylim = range(mtcars$mpg), 
          same_lim = TRUE, width = 300, height = 70
          )
        )
      
      plot <- purrr::map_chr(plot, "svg_text")
    }
  )
Warning: `columns = vars(...)` has been deprecated in gt 0.3.0:
* please use `columns = c(...)` instead
cyl mpg_data
4
6
8

Create a function

We can alternatively write a function to do something similar.

gt_plot <- function(table_data, plot_col, data_col, plot_fun, ...){
  # save the data extract ahead of time 
  # to be used in our anonymous function below
  data_in = purrr::pluck(table_data, "_data", data_col)

  text_transform(
    table_data,
    # note the use of {{}} here - this is tidy eval
    # that allows you to indicate specific columns
    locations = cells_body(columns = vars({{plot_col}})),
    fn = function(x){
      plot <- purrr::map(data_in, plot_fun, width = 300, height = 70, same_lim = FALSE, ...)
      plot_svg <- purrr::map(plot, "svg_text")
      purrr::map(plot_svg, gt::html)
    }
  )
}

And then we can use that function!

mtcars %>% 
  group_by(cyl) %>% 
  summarize(mpg_data = list(mpg), .groups = "drop") %>% 
  gt() %>% 
  # note you can leave mpg_data unquoted for the tidyeval
  # but have to quote mpg_data for the pluck
  gt_plot(mpg_data, "mpg_data", plot_fun = kableExtra::spec_plot)
Warning: `columns = vars(...)` has been deprecated in gt 0.3.0:
* please use `columns = c(...)` instead
cyl mpg_data
4
6
8

Interactive sparklines

We can use the sparkline package to embed interactive sparklines.

gt_spark <- function(table_data, plot_col, data_col){
  # save the data extract ahead of time 
  # to be used in our anonymous function below
  data_in = purrr::pluck(table_data, "_data", data_col)
  
  text_transform(
    table_data,
    # note the use of {{}} here - this is tidy eval
    # that allows you to indicate specific columns
    locations = cells_body(columns = vars({{plot_col}})),
    fn = function(x){
      sparkline_plot <- purrr::map(
        data_in, 
        ~sparkline::spk_chr(values = .x, chartRangeMin = 0)
        )
      
      purrr::map(sparkline_plot, gt::html)
    }
  )
}

We can then apply the function to work very succinctly, referencing only the internal list-column data.

mtcars %>% 
  group_by(cyl) %>% 
  summarize(mpg_data = list(mpg), .groups = "drop") %>% 
  gt() %>% 
  # note you can leave mpg_data unquoted for the tidyeval
  # but have to quote mpg_data for the pluck
  gt_spark(mpg_data, "mpg_data")
Warning: `columns = vars(...)` has been deprecated in gt 0.3.0:
* please use `columns = c(...)` instead
cyl mpg_data
4
6
8

Tooltips

Tooltips can be added with HTML tags.

library(htmltools)

#    
# Add tooltip to column labels
with_tooltip <- function(value, tooltip) {
  tags$abbr(
    style = "text-decoration: underline;
    text-decoration-style: solid; color: blue",
    title = tooltip,
    value
  ) %>% 
    as.character()
}

mtcars %>% 
  head() %>% 
  tibble::rownames_to_column() %>% 
  select(rowname, mpg:hp) %>% 
  gt() %>% 
   cols_label(
    mpg = gt::html(with_tooltip("MPG", "Miles per Gallon")),
    cyl = gt::html(with_tooltip("CYL", "Number of Cylinders")),
    disp = gt::html(with_tooltip("DISP", "Displacement")),
    hp = gt::html(with_tooltip("HP", "Horsepower")),
  )
MPG CYL DISP HP
Mazda RX4 21.0 6 160 110
Mazda RX4 Wag 21.0 6 160 110
Datsun 710 22.8 4 108 93
Hornet 4 Drive 21.4 6 258 110
Hornet Sportabout 18.7 8 360 175
Valiant 18.1 6 225 105

Add icons

You can add arbitrary icons with the fontawesome R package.

mtcars %>% 
  head() %>% 
  gt() %>% 
  text_transform(
    locations = cells_body(columns = vars(cyl), rows = cyl == 4),
    fn = function(x){gt::html(fontawesome::fa("truck-pickup", fill = "blue"))}
  ) %>% 
  text_transform(
    locations = cells_body(columns = vars(cyl), rows = cyl == 6),
    fn = function(x){gt::html(fontawesome::fa("truck", fill = "grey"))}
  ) %>% 
  text_transform(
    locations = cells_body(columns = vars(cyl), rows = cyl == 8),
    fn = function(x){gt::html(fontawesome::fa("truck-monster", fill = "red"))}
  )
Warning: `columns = vars(...)` has been deprecated in gt 0.3.0:
* please use `columns = c(...)` instead

Warning: `columns = vars(...)` has been deprecated in gt 0.3.0:
* please use `columns = c(...)` instead

Warning: `columns = vars(...)` has been deprecated in gt 0.3.0:
* please use `columns = c(...)` instead
mpg cyl disp hp drat wt qsec vs am gear carb
21.0 160 110 3.90 2.620 16.46 0 1 4 4
21.0 160 110 3.90 2.875 17.02 0 1 4 4
22.8 108 93 3.85 2.320 18.61 1 1 4 1
21.4 258 110 3.08 3.215 19.44 1 0 3 1
18.7 360 175 3.15 3.440 17.02 0 0 3 2
18.1 225 105 2.76 3.460 20.22 1 0 3 1

Add rating stars

You can take the icons example a step further, and assign rating stars. For this example, we’re creating HTML content in the data itself, before passing it into gt. This example adapted from reactable.

# note you could use ANY font-awesome logo
# https://fontawesome.com/cheatsheet
rating_stars <- function(rating, max_rating = 5) {
  rounded_rating <- floor(rating + 0.5)  # always round up
  stars <- lapply(seq_len(max_rating), function(i) {
    if (i <= rounded_rating) fontawesome::fa("star", fill= "orange") else fontawesome::fa("star", fill= "grey")
  })
  label <- sprintf("%s out of %s", rating, max_rating)
  div_out <- htmltools::div(title = label, "aria-label" = label, role = "img", stars)
  
  as.character(div_out) %>% 
    gt::html()
}

mtcars %>% 
  slice(1:5) %>% 
  mutate(rating = purrr::map(sample(1:5, size = 5, TRUE), rating_stars)) %>% 
  gt()
mpg cyl disp hp drat wt qsec vs am gear carb rating
21.0 6 160 110 3.90 2.620 16.46 0 1 4 4
21.0 6 160 110 3.90 2.875 17.02 0 1 4 4
22.8 4 108 93 3.85 2.320 18.61 1 1 4 1
21.4 6 258 110 3.08 3.215 19.44 1 0 3 1
18.7 8 360 175 3.15 3.440 17.02 0 0 3 2

Tags and badges

Again we can create a custom function and use purrr::map() to generate the HTML code before passing it into gt. Example adapted from reactable documentation.

add_cyl_color <- function(cyl){
      add_color <- if (cyl == 4) {
        "background: hsl(116, 60%, 90%); color: hsl(116, 30%, 25%);"
      } else if (cyl == 6) {
        "background: hsl(230, 70%, 90%); color: hsl(230, 45%, 30%);"
      } else if (cyl == 8) {
        "background: hsl(350, 70%, 90%); color: hsl(350, 45%, 30%);"
      }
      div_out <- htmltools::div(
        style = paste(
          "display: inline-block; padding: 2px 12px; border-radius: 15px; font-weight: 600; font-size: 12px;",
          add_color
          ),
        paste(cyl, "Cylinders")
      )
      
      as.character(div_out) %>% 
        gt::html()
}

mtcars %>% 
  head() %>% 
  mutate(cylinder = purrr::map(cyl, add_cyl_color)) %>% 
  gt()
mpg cyl disp hp drat wt qsec vs am gear carb cylinder
21.0 6 160 110 3.90 2.620 16.46 0 1 4 4
6 Cylinders
21.0 6 160 110 3.90 2.875 17.02 0 1 4 4
6 Cylinders
22.8 4 108 93 3.85 2.320 18.61 1 1 4 1
4 Cylinders
21.4 6 258 110 3.08 3.215 19.44 1 0 3 1
6 Cylinders
18.7 8 360 175 3.15 3.440 17.02 0 0 3 2
8 Cylinders
18.1 6 225 105 2.76 3.460 20.22 1 0 3 1
6 Cylinders

Badges

We can also use badges in a similar way.

add_badge <- function(x){
      add_color <- if (x == "Paid") {
        "background: hsl(116, 60%, 90%); color: hsl(116, 30%, 25%);"
      } else if (x == "Pending") {
        "background: hsl(230, 70%, 90%); color: hsl(230, 45%, 30%);"
      } else if (x == "Canceled") {
        "background: hsl(350, 70%, 90%); color: hsl(350, 45%, 30%);"
      }
      div_out <- htmltools::div(
        style = paste(
          "display: inline-block; padding: 2px 12px; border-radius: 15px; font-weight: 600; font-size: 12px;",
          add_color
          ),
        x
      )
      
      as.character(div_out) %>% 
        gt::html()
}


orders <- data.frame(
  Order = 2300:2304,
  Created = seq(as.Date("2019-04-01"), by = "day", length.out = 5),
  Customer = sample(rownames(MASS::painters), 5),
  Status = sample(c("Pending", "Paid", "Canceled"), 5, replace = TRUE)
) %>% 
  mutate(Status = purrr::map(Status, add_badge))

orders %>% 
  gt()
Order Created Customer Status
2300 2019-04-01 Lanfranco
Paid
2301 2019-04-02 Van Leyden
Paid
2302 2019-04-03 Da Vinci
Pending
2303 2019-04-04 Caravaggio
Canceled
2304 2019-04-05 Pordenone
Canceled

Expandable sections

You can embed expandable sections with <details> HTML, and we can build up some contents of the details tag with the use of htmltools.

library(htmltools)

source_details <- paste0(
  "<details>", "<summary><strong>Table Key, click to expand</strong></summary>",
  div("cyl: Cylinders"), div("disp: Displacement"), div("hp: Horsepower"),
  "</details"
)

head(mtcars) %>% 
  gt() %>% 
  tab_source_note(source_note = html(source_details))
mpg cyl disp hp drat wt qsec vs am gear carb
21.0 6 160 110 3.90 2.620 16.46 0 1 4 4
21.0 6 160 110 3.90 2.875 17.02 0 1 4 4
22.8 4 108 93 3.85 2.320 18.61 1 1 4 1
21.4 6 258 110 3.08 3.215 19.44 1 0 3 1
18.7 8 360 175 3.15 3.440 17.02 0 0 3 2
18.1 6 225 105 2.76 3.460 20.22 1 0 3 1
Table Key, click to expand
cyl: Cylinders
disp: Displacement
hp: Horsepower

Bar charts

There are different ways to create bar charts, but the example below is adapted from the reactable documentation. The original source on CSS bars using HTML and CSS.

bar_chart <- function(label, height = "16px", fill = "#00bfc4", background = "white") {
  bar <- glue::glue(
    "<div style='background:{fill};width:{label}%;height:{height};'></div>"
    )
  chart <- glue::glue(
    "<div style='flex-grow:1;margin-left:8px;background:{background};'>{bar}</div>"
  )
  glue::glue(
    "<div style='display:flex;align-items:left';>{chart}</div>"
    ) %>%
  gt::html()
  
}

mtcars %>% 
  head() %>% 
  mutate(
    mpg_val = mpg/max(mpg) * 100,
    mpg_plot = purrr::map(mpg_val, ~bar_chart(label = .x)),
    mpg_plot2 = purrr::map(
      mpg_val, 
      ~bar_chart(label = .x, fill = "#fc5185", background = "#e1e1e1")
      ),
    ) %>% 
  select(cyl, hp, disp, mpg, mpg_plot, mpg_plot2) %>% 
  gt() %>% 
  cols_align(align = "left", columns = vars(mpg_plot)) 
Warning: `columns = vars(...)` has been deprecated in gt 0.3.0:
* please use `columns = c(...)` instead
cyl hp disp mpg mpg_plot mpg_plot2
6 110 160 21.0
6 110 160 21.0
4 93 108 22.8
6 110 258 21.4
8 175 360 18.7
6 105 225 18.1

Embed images

The function provides a convenient way to generate an HTML fragment with an image URL. Because this function is currently HTML-based, it is only useful for HTML table output. To use this function inside of data cells, it is recommended that the text_transform() function is used.

r_png_url <- "https://www.r-project.org/logo/Rlogo.png"

dplyr::tibble(
    pixels = px(seq(10, 20, 5)),
    image = seq(10, 20, 5)
  ) %>%
  gt() %>%
  text_transform(
    locations = cells_body(vars(image)),
    fn = function(x) {
      web_image(
        url = r_png_url,
        height = as.numeric(x)
      )
    }
  )
Warning: `columns = vars(...)` has been deprecated in gt 0.3.0:
* please use `columns = c(...)` instead
pixels image
10px
15px
20px

More images

You can include multiple images by parsing the url along with purrr::map() or lapply()

tibble::tribble(
  ~team_abb, ~headshot_href,      ~short_name, ~qbr_total, ~qb_plays,
       "GB",    "8439.png",     "A. Rodgers",       84.4,       608,
       "KC", "3139477.png",     "P. Mahomes",       82.9,       710,
      "BUF", "3918298.png",       "J. Allen",       81.7,       729,
      "TEN",   "14876.png",   "R. Tannehill",       78.3,       594
  ) %>% 
  mutate(
    headshot_href = paste0(
      "https://a.espncdn.com/i/headshots/nfl/players/full/", headshot_href
      )
    ) %>% 
  gt() %>%
  text_transform(
    locations = cells_body(vars(headshot_href)),
    fn = function(x) {purrr::map(x,~ web_image(url = .x, height = 30))}
  )
Warning: `columns = vars(...)` has been deprecated in gt 0.3.0:
* please use `columns = c(...)` instead
team_abb headshot_href short_name qbr_total qb_plays
GB A. Rodgers 84.4 608
KC P. Mahomes 82.9 710
BUF J. Allen 81.7 729
TEN R. Tannehill 78.3 594

gt functions

This section assumes that you become familiar with the {{ var }} syntax, known as “embrace” or “curly curly”. This allows the tidy-evaluation of bare names. A brief example below with a custom function.

ex_function <- function(column){
  mtcars %>% 
    # provide the embrace around the variable name
    # and it can be parsed by tidy-eval
    group_by({{ column }}) %>% 
    summarize(mean = mean(mpg)) %>% 
    ungroup()
}

ex_function(cyl)
# A tibble: 3 × 2
    cyl  mean
  <dbl> <dbl>
1     4  26.7
2     6  19.7
3     8  15.1

While that example shows the usage of {{ var }}, you can also read a bit more in the rlang docs.

Basic functions

You can create repeatable functions with a specific purpose relatively easily with gt.

car_table <- function(grouping){
  mtcars %>% 
    head() %>% 
    gt(groupname_col = grouping) %>% 
    opt_row_striping() %>% 
    tab_options(
      data_row.padding = px(4)
    ) %>% 
    tab_style(
      style = list(
        cell_fill(color = "black"),
        cell_text(color = "white", weight = "bold")
      ),
      locations = cells_row_groups()
    )
}

car_table("am")
mpg cyl disp hp drat wt qsec vs gear carb
1
21.0 6 160 110 3.90 2.620 16.46 0 4 4
21.0 6 160 110 3.90 2.875 17.02 0 4 4
22.8 4 108 93 3.85 2.320 18.61 1 4 1
0
21.4 6 258 110 3.08 3.215 19.44 1 3 1
18.7 8 360 175 3.15 3.440 17.02 0 3 2
18.1 6 225 105 2.76 3.460 20.22 1 3 1


These can be even useful with datasets that are similar in structure (ie same columns), but change week to week, for example reports.

car_table <- function(data_in){
  # provide data_in as an argument, so that the table is similar
  # but the data itself can change
  data_in %>% 
    gt(groupname_col = "cyl") %>% 
    opt_row_striping() %>% 
    tab_options(
      data_row.padding = px(4)
    ) %>% 
    tab_style(
      style = list(
        cell_fill(color = "black"),
        cell_text(color = "white", weight = "bold")
      ),
      locations = cells_row_groups()
    )
}

mtcars %>% 
  slice_sample(n = 12) %>% 
  car_table()
mpg disp hp drat wt qsec vs am gear carb
6
21.0 160.0 110 3.90 2.620 16.46 0 1 4 4
19.7 145.0 175 3.62 2.770 15.50 0 1 5 6
8
15.0 301.0 335 3.54 3.570 14.60 0 1 5 8
10.4 472.0 205 2.93 5.250 17.98 0 0 3 4
15.8 351.0 264 4.22 3.170 14.50 0 1 5 4
19.2 400.0 175 3.08 3.845 17.05 0 0 3 2
14.7 440.0 230 3.23 5.345 17.42 0 0 3 4
4
30.4 95.1 113 3.77 1.513 16.90 1 1 5 2
22.8 108.0 93 3.85 2.320 18.61 1 1 4 1
21.4 121.0 109 4.11 2.780 18.60 1 1 4 2
26.0 120.3 91 4.43 2.140 16.70 0 1 5 2
30.4 75.7 52 4.93 1.615 18.52 1 1 4 2

Create a theme

Creating a theme is similar to a normal function and can be done by passing in a gt object, and setting some parameters in various gt functions. Here we define a basic theme.

my_gt_theme <- function(data, ...) {
  data %>%
    tab_options(
      table.background.color = "black",
      column_labels.background.color = "grey",
      column_labels.font.size = px(16),
      table.font.size = px(12),
      data_row.padding = px(4),
      ...
    )
}

And we can then apply that theme. Note that the theme is intentionally relative garish but we can see that we turned some of the arguments into a one-liner.

head(gtcars) %>% 
  gt() %>% 
  my_gt_theme(table.font.color.light = "lightgreen")
mfr model year trim bdy_style hp hp_rpm trq trq_rpm mpg_c mpg_h drivetrain trsmn ctry_origin msrp
Ford GT 2017 Base Coupe coupe 647 6250 550 5900 11 18 rwd 7a United States 447000
Ferrari 458 Speciale 2015 Base Coupe coupe 597 9000 398 6000 13 17 rwd 7a Italy 291744
Ferrari 458 Spider 2015 Base convertible 562 9000 398 6000 13 17 rwd 7a Italy 263553
Ferrari 458 Italia 2014 Base Coupe coupe 562 9000 398 6000 13 17 rwd 7a Italy 233509
Ferrari 488 GTB 2016 Base Coupe coupe 661 8000 561 3000 15 22 rwd 7a Italy 245400
Ferrari California 2015 Base Convertible convertible 553 7500 557 4750 16 23 rwd 7a Italy 198973

Example Theme

A “prettier” theme based off an ESPN table style.

gt_theme_espn <- function(data, ...){
  data %>% 
    opt_all_caps()  %>%
    opt_table_font(
      font = list(
        google_font("Lato"),
        default_fonts()
      )
    )  %>% 
    opt_row_striping() %>% 
    tab_options(
      row.striping.background_color = "#fafafa",
      table_body.hlines.color = "#f6f7f7",
      source_notes.font.size = 12,
      table.font.size = 16,
      table.width = px(700),
      heading.align = "left",
      heading.title.font.size = 24,
      table.border.top.color = "transparent",
      table.border.top.width = px(3),
      data_row.padding = px(7),
      ...
    ) 
}
head(gtcars) %>% 
  dplyr::select(mfr:mpg_c) %>% 
  gt() %>% 
  gt_theme_espn()
mfr model year trim bdy_style hp hp_rpm trq trq_rpm mpg_c
Ford GT 2017 Base Coupe coupe 647 6250 550 5900 11
Ferrari 458 Speciale 2015 Base Coupe coupe 597 9000 398 6000 13
Ferrari 458 Spider 2015 Base convertible 562 9000 398 6000 13
Ferrari 458 Italia 2014 Base Coupe coupe 562 9000 398 6000 13
Ferrari 488 GTB 2016 Base Coupe coupe 661 8000 561 3000 15
Ferrari California 2015 Base Convertible convertible 553 7500 557 4750 16

FiveThirtyEight Theme

My favorite tables come from FiveThirtyEight, so here is an example theme that closely follows their style.

gt_theme_538 <- function(data,...) {
  data %>%
  opt_all_caps()  %>%
  opt_table_font(
    font = list(
      google_font("Chivo"),
      default_fonts()
    )
  ) %>%
    tab_style(
      style = cell_borders(
        sides = "bottom", color = "transparent", weight = px(2)
      ),
      locations = cells_body(
        columns = TRUE,
        # This is a relatively sneaky way of changing the bottom border
        # Regardless of data size
        rows = nrow(data$`_data`)
      )
    )  %>% 
  tab_options(
    column_labels.background.color = "white",
    table.border.top.width = px(3),
    table.border.top.color = "transparent",
    table.border.bottom.color = "transparent",
    table.border.bottom.width = px(3),
    column_labels.border.top.width = px(3),
    column_labels.border.top.color = "transparent",
    column_labels.border.bottom.width = px(3),
    column_labels.border.bottom.color = "black",
    data_row.padding = px(3),
    source_notes.font.size = 12,
    table.font.size = 16,
    heading.align = "left",
    ...
  ) 
}
head(gtcars) %>% 
  dplyr::select(mfr:mpg_c) %>% 
  gt() %>% 
  gt_theme_538() 
Warning: `columns = TRUE` has been deprecated in gt 0.3.0:
* please use `columns = everything()` instead
mfr model year trim bdy_style hp hp_rpm trq trq_rpm mpg_c
Ford GT 2017 Base Coupe coupe 647 6250 550 5900 11
Ferrari 458 Speciale 2015 Base Coupe coupe 597 9000 398 6000 13
Ferrari 458 Spider 2015 Base convertible 562 9000 398 6000 13
Ferrari 458 Italia 2014 Base Coupe coupe 562 9000 398 6000 13
Ferrari 488 GTB 2016 Base Coupe coupe 661 8000 561 3000 15
Ferrari California 2015 Base Convertible convertible 553 7500 557 4750 16

Tidy eval

Now, I want to preface this by saying that the entire tidyeval framework used in gt is currently under active development to be more closely aligned with the tidyverse. You’ll note the relatively legacy use of vars() inside gt.

Most of this is only required for creating your own functions, although there are some sharp edges around specifying columns in vars().

For some nice reading about tidyeval beyond the scope of just gt, see:

To start off, let’s revisit an example from the cookbook. First we’ll prep the data.

dimnames <- list(start(nottem)[1]:end(nottem)[1], month.abb)
temps <- matrix(nottem, ncol = 12, byrow = TRUE, dimnames = dimnames) %>% 
  data.frame() %>% 
  tibble::rownames_to_column() %>% 
  head(10)

temps %>% 
  tibble()
# A tibble: 10 × 13
   rowname   Jan   Feb   Mar   Apr   May   Jun   Jul   Aug   Sep   Oct   Nov
   <chr>   <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
 1 1920     40.6  40.8  44.4  46.7  54.1  58.5  57.7  56.4  54.3  50.5  42.9
 2 1921     44.2  39.8  45.1  47    54.1  58.7  66.3  59.9  57    54.2  39.7
 3 1922     37.5  38.7  39.5  42.1  55.7  57.8  56.8  54.3  54.3  47.1  41.8
 4 1923     41.8  40.1  42.9  45.8  49.2  52.7  64.2  59.6  54.4  49.2  36.3
 5 1924     39.3  37.5  38.3  45.5  53.2  57.7  60.8  58.2  56.4  49.8  44.4
 6 1925     40    40.5  40.8  45.1  53.8  59.4  63.5  61    53    50    38.1
 7 1926     39.2  43.4  43.4  48.9  50.6  56.8  62.5  62    57.5  46.7  41.6
 8 1927     39.4  38.5  45.3  47.1  51.7  55    60.4  60.5  54.7  50.3  42.3
 9 1928     40.8  41.1  42.8  47.3  50.9  56.4  62.2  60.5  55.4  50.2  43  
10 1929     34.8  31.3  41    43.9  53.1  56.9  62.5  60.3  59.8  49.2  42.9
# … with 1 more variable: Dec <dbl>



We’ll also define our “Hulk palette” as a function.

hulk_pal <- function(x){
  scales::col_numeric(
      colorspace::diverge_hcl(n = 9, palette = "Purple-Green") %>% rev(), 
      domain = range(nottem)
      )(x)
}

This function supplies a number or a vector of numbers to generate colors.

# January is cold
temps$Jan %>% hulk_pal() %>%  scales::show_col()

# June is warm
temps$Jun %>% hulk_pal() %>%  scales::show_col()

Sequence of columns

You may typically use something like Jan:Dec to indicate the columns from Jan TO Dec, but this won’t work in vars(). This throws an error Error: Can't convert a call to a string. However we can accomplish similar things through other techniques.

temps %>% 
  gt() %>% 
  data_color(
    # note use of sequence
    columns = vars(Jan:Dec),
    colors = hulk_pal
  )

#> Error: Can't convert a call to a string

Raw strings

You can pass raw strings into vars(). Since our names of the columns are month abbreviation, we can take advantage of the built in month.abb string.

month.abb
 [1] "Jan" "Feb" "Mar" "Apr" "May" "Jun" "Jul" "Aug" "Sep" "Oct" "Nov" "Dec"

We can compare the code for the below, note the use of month.abb first or manually naming ALL the column names second.

temps %>% 
  gt() %>% 
  data_color(
    # note use of month.abb
    columns = vars(month.abb),
    colors = hulk_pal
  )
Warning: `columns = vars(...)` has been deprecated in gt 0.3.0:
* please use `columns = c(...)` instead
Note: Using an external vector in selections is ambiguous.
ℹ Use `all_of(month.abb)` instead of `month.abb` to silence this message.
ℹ See <https://tidyselect.r-lib.org/reference/faq-external-vector.html>.
This message is displayed once per session.
Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec
1920 40.6 40.8 44.4 46.7 54.1 58.5 57.7 56.4 54.3 50.5 42.9 39.8
1921 44.2 39.8 45.1 47.0 54.1 58.7 66.3 59.9 57.0 54.2 39.7 42.8
1922 37.5 38.7 39.5 42.1 55.7 57.8 56.8 54.3 54.3 47.1 41.8 41.7
1923 41.8 40.1 42.9 45.8 49.2 52.7 64.2 59.6 54.4 49.2 36.3 37.6
1924 39.3 37.5 38.3 45.5 53.2 57.7 60.8 58.2 56.4 49.8 44.4 43.6
1925 40.0 40.5 40.8 45.1 53.8 59.4 63.5 61.0 53.0 50.0 38.1 36.3
1926 39.2 43.4 43.4 48.9 50.6 56.8 62.5 62.0 57.5 46.7 41.6 39.8
1927 39.4 38.5 45.3 47.1 51.7 55.0 60.4 60.5 54.7 50.3 42.3 35.2
1928 40.8 41.1 42.8 47.3 50.9 56.4 62.2 60.5 55.4 50.2 43.0 37.3
1929 34.8 31.3 41.0 43.9 53.1 56.9 62.5 60.3 59.8 49.2 42.9 41.9



temps %>% 
  gt() %>% 
  data_color(
    columns = vars(
      Jan, Feb, Mar, Apr, May, Jun, 
      Jul, Aug, Sep, Oct, Nov, Dec
      ),
    colors = hulk_pal
  )
Warning: `columns = vars(...)` has been deprecated in gt 0.3.0:
* please use `columns = c(...)` instead
Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec
1920 40.6 40.8 44.4 46.7 54.1 58.5 57.7 56.4 54.3 50.5 42.9 39.8
1921 44.2 39.8 45.1 47.0 54.1 58.7 66.3 59.9 57.0 54.2 39.7 42.8
1922 37.5 38.7 39.5 42.1 55.7 57.8 56.8 54.3 54.3 47.1 41.8 41.7
1923 41.8 40.1 42.9 45.8 49.2 52.7 64.2 59.6 54.4 49.2 36.3 37.6
1924 39.3 37.5 38.3 45.5 53.2 57.7 60.8 58.2 56.4 49.8 44.4 43.6
1925 40.0 40.5 40.8 45.1 53.8 59.4 63.5 61.0 53.0 50.0 38.1 36.3
1926 39.2 43.4 43.4 48.9 50.6 56.8 62.5 62.0 57.5 46.7 41.6 39.8
1927 39.4 38.5 45.3 47.1 51.7 55.0 60.4 60.5 54.7 50.3 42.3 35.2
1928 40.8 41.1 42.8 47.3 50.9 56.4 62.2 60.5 55.4 50.2 43.0 37.3
1929 34.8 31.3 41.0 43.9 53.1 56.9 62.5 60.3 59.8 49.2 42.9 41.9

Numbered

Now you can skip using vars() and the named column and just supply the column number. This is a great usecase if you have a lot of columns that need to be used and want a low-effort way of indicating.

temps %>% 
  gt() %>% 
  data_color(
    columns = 2:13,
    colors = hulk_pal
  )
Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec
1920 40.6 40.8 44.4 46.7 54.1 58.5 57.7 56.4 54.3 50.5 42.9 39.8
1921 44.2 39.8 45.1 47.0 54.1 58.7 66.3 59.9 57.0 54.2 39.7 42.8
1922 37.5 38.7 39.5 42.1 55.7 57.8 56.8 54.3 54.3 47.1 41.8 41.7
1923 41.8 40.1 42.9 45.8 49.2 52.7 64.2 59.6 54.4 49.2 36.3 37.6
1924 39.3 37.5 38.3 45.5 53.2 57.7 60.8 58.2 56.4 49.8 44.4 43.6
1925 40.0 40.5 40.8 45.1 53.8 59.4 63.5 61.0 53.0 50.0 38.1 36.3
1926 39.2 43.4 43.4 48.9 50.6 56.8 62.5 62.0 57.5 46.7 41.6 39.8
1927 39.4 38.5 45.3 47.1 51.7 55.0 60.4 60.5 54.7 50.3 42.3 35.2
1928 40.8 41.1 42.8 47.3 50.9 56.4 62.2 60.5 55.4 50.2 43.0 37.3
1929 34.8 31.3 41.0 43.9 53.1 56.9 62.5 60.3 59.8 49.2 42.9 41.9

Names

You can subset the names of the column but without using tidyeval must assign it to an object to use it inside vars().

cols_affect <- names(temps)[2:13]

temps %>% 
  gt() %>% 
  data_color(
    columns = vars(cols_affect),
    colors = hulk_pal
  )
Warning: `columns = vars(...)` has been deprecated in gt 0.3.0:
* please use `columns = c(...)` instead
Note: Using an external vector in selections is ambiguous.
ℹ Use `all_of(cols_affect)` instead of `cols_affect` to silence this message.
ℹ See <https://tidyselect.r-lib.org/reference/faq-external-vector.html>.
This message is displayed once per session.
Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec
1920 40.6 40.8 44.4 46.7 54.1 58.5 57.7 56.4 54.3 50.5 42.9 39.8
1921 44.2 39.8 45.1 47.0 54.1 58.7 66.3 59.9 57.0 54.2 39.7 42.8
1922 37.5 38.7 39.5 42.1 55.7 57.8 56.8 54.3 54.3 47.1 41.8 41.7
1923 41.8 40.1 42.9 45.8 49.2 52.7 64.2 59.6 54.4 49.2 36.3 37.6
1924 39.3 37.5 38.3 45.5 53.2 57.7 60.8 58.2 56.4 49.8 44.4 43.6
1925 40.0 40.5 40.8 45.1 53.8 59.4 63.5 61.0 53.0 50.0 38.1 36.3
1926 39.2 43.4 43.4 48.9 50.6 56.8 62.5 62.0 57.5 46.7 41.6 39.8
1927 39.4 38.5 45.3 47.1 51.7 55.0 60.4 60.5 54.7 50.3 42.3 35.2
1928 40.8 41.1 42.8 47.3 50.9 56.4 62.2 60.5 55.4 50.2 43.0 37.3
1929 34.8 31.3 41.0 43.9 53.1 56.9 62.5 60.3 59.8 49.2 42.9 41.9

Names + !!!

If you use tidyeval’s bang-bang-bang operator (!!!), then you can parse the R code inside the vars() call.

temps %>% 
  gt() %>% 
  data_color(
    columns = vars(!!!names(temps)[2:13]),
    colors = hulk_pal
  )
Warning: `columns = vars(...)` has been deprecated in gt 0.3.0:
* please use `columns = c(...)` instead
Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec
1920 40.6 40.8 44.4 46.7 54.1 58.5 57.7 56.4 54.3 50.5 42.9 39.8
1921 44.2 39.8 45.1 47.0 54.1 58.7 66.3 59.9 57.0 54.2 39.7 42.8
1922 37.5 38.7 39.5 42.1 55.7 57.8 56.8 54.3 54.3 47.1 41.8 41.7
1923 41.8 40.1 42.9 45.8 49.2 52.7 64.2 59.6 54.4 49.2 36.3 37.6
1924 39.3 37.5 38.3 45.5 53.2 57.7 60.8 58.2 56.4 49.8 44.4 43.6
1925 40.0 40.5 40.8 45.1 53.8 59.4 63.5 61.0 53.0 50.0 38.1 36.3
1926 39.2 43.4 43.4 48.9 50.6 56.8 62.5 62.0 57.5 46.7 41.6 39.8
1927 39.4 38.5 45.3 47.1 51.7 55.0 60.4 60.5 54.7 50.3 42.3 35.2
1928 40.8 41.1 42.8 47.3 50.9 56.4 62.2 60.5 55.4 50.2 43.0 37.3
1929 34.8 31.3 41.0 43.9 53.1 56.9 62.5 60.3 59.8 49.2 42.9 41.9

Strings

You can pass raw strings to vars() and separate them by commas.

temps %>% 
  gt() %>% 
  data_color(
    columns = vars("Jan", "Feb"),
    colors = hulk_pal
  )
Warning: `columns = vars(...)` has been deprecated in gt 0.3.0:
* please use `columns = c(...)` instead
Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec
1920 40.6 40.8 44.4 46.7 54.1 58.5 57.7 56.4 54.3 50.5 42.9 39.8
1921 44.2 39.8 45.1 47.0 54.1 58.7 66.3 59.9 57.0 54.2 39.7 42.8
1922 37.5 38.7 39.5 42.1 55.7 57.8 56.8 54.3 54.3 47.1 41.8 41.7
1923 41.8 40.1 42.9 45.8 49.2 52.7 64.2 59.6 54.4 49.2 36.3 37.6
1924 39.3 37.5 38.3 45.5 53.2 57.7 60.8 58.2 56.4 49.8 44.4 43.6
1925 40.0 40.5 40.8 45.1 53.8 59.4 63.5 61.0 53.0 50.0 38.1 36.3
1926 39.2 43.4 43.4 48.9 50.6 56.8 62.5 62.0 57.5 46.7 41.6 39.8
1927 39.4 38.5 45.3 47.1 51.7 55.0 60.4 60.5 54.7 50.3 42.3 35.2
1928 40.8 41.1 42.8 47.3 50.9 56.4 62.2 60.5 55.4 50.2 43.0 37.3
1929 34.8 31.3 41.0 43.9 53.1 56.9 62.5 60.3 59.8 49.2 42.9 41.9

Strings + c()

IF you use a c() you need to use the !!! operator. More details at Advanced R.

temps %>% 
  gt() %>% 
  data_color(
    columns = vars(!!!c("Jan", "Feb")),
    colors = hulk_pal
  )
Warning: `columns = vars(...)` has been deprecated in gt 0.3.0:
* please use `columns = c(...)` instead
Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec
1920 40.6 40.8 44.4 46.7 54.1 58.5 57.7 56.4 54.3 50.5 42.9 39.8
1921 44.2 39.8 45.1 47.0 54.1 58.7 66.3 59.9 57.0 54.2 39.7 42.8
1922 37.5 38.7 39.5 42.1 55.7 57.8 56.8 54.3 54.3 47.1 41.8 41.7
1923 41.8 40.1 42.9 45.8 49.2 52.7 64.2 59.6 54.4 49.2 36.3 37.6
1924 39.3 37.5 38.3 45.5 53.2 57.7 60.8 58.2 56.4 49.8 44.4 43.6
1925 40.0 40.5 40.8 45.1 53.8 59.4 63.5 61.0 53.0 50.0 38.1 36.3
1926 39.2 43.4 43.4 48.9 50.6 56.8 62.5 62.0 57.5 46.7 41.6 39.8
1927 39.4 38.5 45.3 47.1 51.7 55.0 60.4 60.5 54.7 50.3 42.3 35.2
1928 40.8 41.1 42.8 47.3 50.9 56.4 62.2 60.5 55.4 50.2 43.0 37.3
1929 34.8 31.3 41.0 43.9 53.1 56.9 62.5 60.3 59.8 49.2 42.9 41.9

Functions

Functions require some special subsets of tidyeval. There are multiple ways to approach this with the current implementation of tidyeval, although this will hopefully become even more robust over time as the gt team continues to develop the package.

Pass the dots

For representing multiple columns at once, you can just “pass the dots” into the function. More details about the dots.

color_columns <- function(data_in, ..., palette = hulk_pal) {
  data_in %>%
    gt() %>%
    data_color(
      columns = vars(...),
      colors = palette
    )
}

color_columns(temps, Jan, Feb, Mar, Apr, May, Jun)
Warning: `columns = vars(...)` has been deprecated in gt 0.3.0:
* please use `columns = c(...)` instead
Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec
1920 40.6 40.8 44.4 46.7 54.1 58.5 57.7 56.4 54.3 50.5 42.9 39.8
1921 44.2 39.8 45.1 47.0 54.1 58.7 66.3 59.9 57.0 54.2 39.7 42.8
1922 37.5 38.7 39.5 42.1 55.7 57.8 56.8 54.3 54.3 47.1 41.8 41.7
1923 41.8 40.1 42.9 45.8 49.2 52.7 64.2 59.6 54.4 49.2 36.3 37.6
1924 39.3 37.5 38.3 45.5 53.2 57.7 60.8 58.2 56.4 49.8 44.4 43.6
1925 40.0 40.5 40.8 45.1 53.8 59.4 63.5 61.0 53.0 50.0 38.1 36.3
1926 39.2 43.4 43.4 48.9 50.6 56.8 62.5 62.0 57.5 46.7 41.6 39.8
1927 39.4 38.5 45.3 47.1 51.7 55.0 60.4 60.5 54.7 50.3 42.3 35.2
1928 40.8 41.1 42.8 47.3 50.9 56.4 62.2 60.5 55.4 50.2 43.0 37.3
1929 34.8 31.3 41.0 43.9 53.1 56.9 62.5 60.3 59.8 49.2 42.9 41.9

Wrapper

Similarly, this could just be a wrapper around data_color alone, rather than the full gt pipeline.

data_color_cols <- function(gt_data, ..., palette = hulk_pal) {
  gt_data %>%
    data_color(
      columns = vars(...),
      colors = palette
    )
}

temps %>% 
  gt() %>% 
  data_color_cols(Jan, Feb, Mar, Apr, May, Jun)
Warning: `columns = vars(...)` has been deprecated in gt 0.3.0:
* please use `columns = c(...)` instead
Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec
1920 40.6 40.8 44.4 46.7 54.1 58.5 57.7 56.4 54.3 50.5 42.9 39.8
1921 44.2 39.8 45.1 47.0 54.1 58.7 66.3 59.9 57.0 54.2 39.7 42.8
1922 37.5 38.7 39.5 42.1 55.7 57.8 56.8 54.3 54.3 47.1 41.8 41.7
1923 41.8 40.1 42.9 45.8 49.2 52.7 64.2 59.6 54.4 49.2 36.3 37.6
1924 39.3 37.5 38.3 45.5 53.2 57.7 60.8 58.2 56.4 49.8 44.4 43.6
1925 40.0 40.5 40.8 45.1 53.8 59.4 63.5 61.0 53.0 50.0 38.1 36.3
1926 39.2 43.4 43.4 48.9 50.6 56.8 62.5 62.0 57.5 46.7 41.6 39.8
1927 39.4 38.5 45.3 47.1 51.7 55.0 60.4 60.5 54.7 50.3 42.3 35.2
1928 40.8 41.1 42.8 47.3 50.9 56.4 62.2 60.5 55.4 50.2 43.0 37.3
1929 34.8 31.3 41.0 43.9 53.1 56.9 62.5 60.3 59.8 49.2 42.9 41.9

Function + Strings

If you’d like to avoid using ... or would prefer strings, you can pass raw strings vars() and use !!! to parse the vector of strings.

data_color_cols <- function(gt_data, columns, palette = hulk_pal) {

  gt_data %>%
    data_color(
      columns = vars(!!!columns),
      colors = palette
    )
}

temps %>% 
  gt() %>% 
  data_color_cols(columns = c("Jan", "Feb", "Mar"))
Warning: `columns = vars(...)` has been deprecated in gt 0.3.0:
* please use `columns = c(...)` instead
Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec
1920 40.6 40.8 44.4 46.7 54.1 58.5 57.7 56.4 54.3 50.5 42.9 39.8
1921 44.2 39.8 45.1 47.0 54.1 58.7 66.3 59.9 57.0 54.2 39.7 42.8
1922 37.5 38.7 39.5 42.1 55.7 57.8 56.8 54.3 54.3 47.1 41.8 41.7
1923 41.8 40.1 42.9 45.8 49.2 52.7 64.2 59.6 54.4 49.2 36.3 37.6
1924 39.3 37.5 38.3 45.5 53.2 57.7 60.8 58.2 56.4 49.8 44.4 43.6
1925 40.0 40.5 40.8 45.1 53.8 59.4 63.5 61.0 53.0 50.0 38.1 36.3
1926 39.2 43.4 43.4 48.9 50.6 56.8 62.5 62.0 57.5 46.7 41.6 39.8
1927 39.4 38.5 45.3 47.1 51.7 55.0 60.4 60.5 54.7 50.3 42.3 35.2
1928 40.8 41.1 42.8 47.3 50.9 56.4 62.2 60.5 55.4 50.2 43.0 37.3
1929 34.8 31.3 41.0 43.9 53.1 56.9 62.5 60.3 59.8 49.2 42.9 41.9

Embrace

The embracing operator {{ }} can be used for single columns.

color_column <- function(data_in, column, palette = hulk_pal) {

  data_in %>%
    gt() %>%
    data_color(
      columns = vars({{column}}),
      colors = palette
    )
}

color_columns(temps, Jun)
Warning: `columns = vars(...)` has been deprecated in gt 0.3.0:
* please use `columns = c(...)` instead
Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec
1920 40.6 40.8 44.4 46.7 54.1 58.5 57.7 56.4 54.3 50.5 42.9 39.8
1921 44.2 39.8 45.1 47.0 54.1 58.7 66.3 59.9 57.0 54.2 39.7 42.8
1922 37.5 38.7 39.5 42.1 55.7 57.8 56.8 54.3 54.3 47.1 41.8 41.7
1923 41.8 40.1 42.9 45.8 49.2 52.7 64.2 59.6 54.4 49.2 36.3 37.6
1924 39.3 37.5 38.3 45.5 53.2 57.7 60.8 58.2 56.4 49.8 44.4 43.6
1925 40.0 40.5 40.8 45.1 53.8 59.4 63.5 61.0 53.0 50.0 38.1 36.3
1926 39.2 43.4 43.4 48.9 50.6 56.8 62.5 62.0 57.5 46.7 41.6 39.8
1927 39.4 38.5 45.3 47.1 51.7 55.0 60.4 60.5 54.7 50.3 42.3 35.2
1928 40.8 41.1 42.8 47.3 50.9 56.4 62.2 60.5 55.4 50.2 43.0 37.3
1929 34.8 31.3 41.0 43.9 53.1 56.9 62.5 60.3 59.8 49.2 42.9 41.9

Wrapper

Similarly, this could just be a wrapper around data_color alone, rather than the full gt pipeline.

data_color_col <- function(gt_data, column, palette = hulk_pal) {

  gt_data %>%
    data_color(
      columns = vars({{column}}),
      colors = palette
    )
}

temps %>% 
  gt() %>% 
  data_color_col(column = Jun)
Warning: `columns = vars(...)` has been deprecated in gt 0.3.0:
* please use `columns = c(...)` instead
Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec
1920 40.6 40.8 44.4 46.7 54.1 58.5 57.7 56.4 54.3 50.5 42.9 39.8
1921 44.2 39.8 45.1 47.0 54.1 58.7 66.3 59.9 57.0 54.2 39.7 42.8
1922 37.5 38.7 39.5 42.1 55.7 57.8 56.8 54.3 54.3 47.1 41.8 41.7
1923 41.8 40.1 42.9 45.8 49.2 52.7 64.2 59.6 54.4 49.2 36.3 37.6
1924 39.3 37.5 38.3 45.5 53.2 57.7 60.8 58.2 56.4 49.8 44.4 43.6
1925 40.0 40.5 40.8 45.1 53.8 59.4 63.5 61.0 53.0 50.0 38.1 36.3
1926 39.2 43.4 43.4 48.9 50.6 56.8 62.5 62.0 57.5 46.7 41.6 39.8
1927 39.4 38.5 45.3 47.1 51.7 55.0 60.4 60.5 54.7 50.3 42.3 35.2
1928 40.8 41.1 42.8 47.3 50.9 56.4 62.2 60.5 55.4 50.2 43.0 37.3
1929 34.8 31.3 41.0 43.9 53.1 56.9 62.5 60.3 59.8 49.2 42.9 41.9