The fmt_tf() function

Let’s use a subset of the sp500 dataset to create a small gt table containing opening and closing price data for a week in 2013. We can add a logical column (dir) with cols_add(); the expression used determines whether the close value is greater than the open value. That new column is inserted between open and close. Then, we use fmt_tf() to generate up and down arrows in the dir column. We elect to use green upward arrows and red downward arrows (through the colors option). With a little numeric formatting and changes to the column labels, the table becomes more presentable.

sp500 |>
  dplyr::filter(date >= "2013-01-07" & date <= "2013-01-12") |>
  dplyr::arrange(date) |>
  dplyr::select(-c(adj_close, volume, high, low)) |>
  gt(rowname_col = "date") |>
  cols_add(dir = close > open, .after = open) |>
  fmt_tf(
    columns = dir,
    tf_style = "arrows",
    colors = c("green", "red")
  ) |>
  fmt_currency(columns = c(open, close)) |>
  cols_label(
    open = "Opening",
    close = "Closing",
    dir = ""
  )
Opening Closing
2013-01-07 $1,466.47 $1,461.89
2013-01-08 $1,461.89 $1,457.15
2013-01-09 $1,457.15 $1,461.02
2013-01-10 $1,461.02 $1,472.12
2013-01-11 $1,472.12 $1,472.05

The reactions dataset contains chemical kinetic information on a wide variety of atmospherically-relevant compounds. It might be interesting to get a summary (for a small subset of compounds) for which rate constants are available for the selected compounds. We first start by selecting the relevant rows and columns. Then we generate logical columns for each of the reaction types (i.e., if a value is NA then there’s no measurement, so that’s FALSE). Once the gt table has been created, we can use fmt_tf() to provide open and filled circles to indicate whether a particular reaction has been measured and presented in the literature.

reactions |>
  dplyr::filter(cmpd_type %in% c("carboxylic acid", "alkyne", "allene")) |>
  dplyr::select(cmpd_name, cmpd_type, ends_with("k298")) |>
  dplyr::mutate(across(ends_with("k298"), is.na)) |>
  gt(rowname_col = "cmpd_name", groupname_col = "cmpd_type") |>
  tab_spanner(
    label = "Has a measured rate constant",
    columns = ends_with("k298")
  ) |>
  tab_stub_indent(
    rows = everything(),
    indent = 2
  ) |>
  fmt_tf(
    columns = ends_with("k298"),
    tf_style = "circles"
  ) |>
  cols_label(
    OH_k298 = "OH",
    O3_k298 = "Ozone",
    NO3_k298 = "Nitrate",
    Cl_k298 = "Chlorine"
  ) |>
  cols_width(
    stub() ~ px(200),
    ends_with("k298") ~ px(80)
  ) |>
  opt_vertical_padding(scale = 0.35)
Has a measured rate constant
OH Ozone Nitrate Chlorine
carboxylic acid
formic acid
acetic acid
propanoic acid
2-methylpropanoic acid
butanoic acid
alkyne
acetylene
propyne
2-butyne
1-butyne
1-pentyne
2-hexyne
1-hexyne
diacetylene
allene
allene
methylallene
3-methyl-1,2-butadiene
1,2-pentadiene
2,3-pentadiene

There are census-based population values in the towny dataset and quite a few small towns within it. Let’s look at the ten smallest towns (according to the 2021 figures) and work out whether their populations have increased or declined since 1996. Also, let’s determine which of these towns even have a website. After that data preparation, the data is made into a gt table and fmt_tf() can be used in the website and pop_dir columns (which both have TRUE/FALSE values). Each of these fmt_tf() calls will either produce "yes"/"no" or "up"/"down" strings (set via the tf_style option).

towny |>
  dplyr::arrange(population_2021) |>
  dplyr::mutate(website = !is.na(website))  |>
  dplyr::mutate(pop_dir = population_2021 > population_1996) |>
  dplyr::select(name, website, population_1996, population_2021, pop_dir) |>
  dplyr::slice_head(n = 10) |>
  gt(rowname_col = "name") |>
  tab_spanner(
    label = "Population",
    columns = starts_with("pop")
  ) |>
  tab_stubhead(label = "Town") |>
  fmt_tf(
    columns = website,
    tf_style = "yes-no",
    auto_align = FALSE
  ) |>
  fmt_tf(
    columns = pop_dir,
    tf_style = "up-down",
    pattern = "It's {x}."
  ) |>
  cols_label_with(
    columns = starts_with("population"),
    fn = function(x) sub("population_", "", x)
  ) |>
  cols_label(
    website = md("Has a  \\n website?"),
    pop_dir = "Pop. direction?"
  ) |>
  opt_horizontal_padding(scale = 2)
Town Has a \n website?
Population
1996 2021 Pop. direction?
Cockburn Island yes 2 16 It's up.
Thornloe no 132 92 It's down.
Brethour no 181 105 It's down.
Gauthier no 152 151 It's down.
Mattawan yes 115 153 It's up.
Hilton Beach yes 213 198 It's down.
Opasatika yes 349 200 It's down.
Hilliard yes 253 215 It's down.
Pelee yes 283 230 It's down.
Head, Clara and Maria yes 294 267 It's down.

If formatting to words instead of symbols (with the hyphenated tf_style keywords), the words themselves can be translated to different languages if providing a locale value. In this next example, we’re manually creating a tibble with locale codes and their associated languages. The yes and up columns all receive TRUE whereas no and down will all be FALSE. With two calls of fmt_tf() for each of these pairings, we get the columns’ namesake words. To have these words translated, the locale argument is pointed toward values in the code column by using from_column().

dplyr::tibble(
  code = c("de", "fr", "is", "tr", "ka", "lt", "ca", "bg", "lv"),
  lang = c(
    "German", "French", "Icelandic", "Turkish", "Georgian",
    "Lithuanian", "Catalan", "Bulgarian", "Latvian"
  ),
  yes = TRUE,
  no = FALSE,
  up = TRUE,
  down = FALSE
) |>
  gt(rowname_col = "lang") |>
  tab_header(title = "Common words in a few languages") |>
  fmt_tf(
    columns = c(yes, no),
    tf_style = "yes-no",
    locale = from_column("code")
  ) |>
  fmt_tf(
    columns = c(up, down),
    tf_style = "up-down",
    locale = from_column("code")
  ) |>
  cols_merge(
    columns = c(lang, code),
    pattern = "{1} ({2})"
  ) |>
  cols_width(
    stub() ~ px(150),
    everything() ~ px(80)
  )
Common words in a few languages
yes no up down
German (de) ja nein oben unten
French (fr) oui non haut bas
Icelandic (is) nei upp niður
Turkish (tr) evet hayir yukarı aşağı
Georgian (ka) კი არა ზევით ქვემოთ
Lithuanian (lt) taip ne aukštyn žemyn
Catalan (ca) no amunt avall
Bulgarian (bg) да не нагоре надолу
Latvian (lv) uz augšu uz leju