The cols_add() function

Let’s take a subset of the exibble dataset and make a simple gt table with it (using the row column for labels in the stub). We’ll add a single column to the right of all the existing columns and call it country. This new column needs eight values and these will be supplied when using cols_add().

exibble |>
  dplyr::select(num, char, datetime, currency, group) |>
  gt(rowname_col = "row") |>
  cols_add(
    country = c("TL", "PY", "GL", "PA", "MO", "EE", "CO", "AU")
  )
num char datetime currency group country
1.111e-01 apricot 2018-01-01 02:22 49.950 grp_a TL
2.222e+00 banana 2018-02-02 14:33 17.950 grp_a PY
3.333e+01 coconut 2018-03-03 03:44 1.390 grp_a GL
4.444e+02 durian 2018-04-04 15:55 65100.000 grp_a PA
5.550e+03 NA 2018-05-05 04:00 1325.810 grp_b MO
NA fig 2018-06-06 16:11 13.255 grp_b EE
7.770e+05 grapefruit 2018-07-07 05:22 NA grp_b CO
8.880e+06 honeydew NA 0.440 grp_b AU

We can add multiple columns with a single use of cols_add(). The columns generated can be formatted and otherwise manipulated just as any column could be in a gt table. The following example extends the first one by adding more columns and immediately using them in various function calls like fmt_flag() and fmt_units().

exibble |>
  dplyr::select(num, char, datetime, currency, group) |>
  gt(rowname_col = "row") |>
  cols_add(
    country = c("TL", "PY", "GL", "PA", "MO", "EE", "CO", "AU"),
    empty = NA_character_,
    units = c(
      "k m s^-2", "N m^-2", "degC", "m^2 kg s^-2",
      "m^2 kg s^-3", "/s", "A s", "m^2 kg s^-3 A^-1"
    ),
    big_num = num ^ 3
  ) |>
  fmt_flag(columns = country) |>
  sub_missing(columns = empty, missing_text = "") |>
  fmt_units(columns = units) |>
  fmt_scientific(columns = big_num)
num char datetime currency group country empty units big_num
1.111e-01 apricot 2018-01-01 02:22 49.950 grp_a
k m s−2 1.37 × 10−3
2.222e+00 banana 2018-02-02 14:33 17.950 grp_a
N m−2 1.10 × 101
3.333e+01 coconut 2018-03-03 03:44 1.390 grp_a
°C 3.70 × 104
4.444e+02 durian 2018-04-04 15:55 65100.000 grp_a
m2 kg s−2 8.78 × 107
5.550e+03 NA 2018-05-05 04:00 1325.810 grp_b
m2 kg s−3 1.71 × 1011
NA fig 2018-06-06 16:11 13.255 grp_b
s−1 NA
7.770e+05 grapefruit 2018-07-07 05:22 NA grp_b
A s 4.69 × 1017
8.880e+06 honeydew NA 0.440 grp_b
m2 kg s−3 A−1 7.00 × 1020

In this table generated from a portion of the towny dataset, we add two new columns (land_area and density) through a single use of cols_add(). The new land_area column is a conversion of land area from square kilometers to square miles and the density column is calculated by through division of population_2021 by that new land_area column. We hide the now unneeded land_area_km2 with cols_hide() and also perform some column labeling and adjustments to column widths with cols_label() and cols_width().

towny |>
  dplyr::select(name, population_2021, land_area_km2) |>
  dplyr::filter(population_2021 > 100000) |>
  dplyr::slice_max(population_2021, n = 10) |>
  gt() |>
  cols_add(
    land_area = land_area_km2 / 2.58998811,
    density = population_2021 / land_area
  ) |>
  fmt_integer() |>
  cols_hide(columns = land_area_km2) |>
  cols_label(
    population_2021 = "Population",
    density = "Density, {{*persons* / sq mi}}",
    land_area ~ "Area, {{mi^2}}"
  ) |>
  cols_width(everything() ~ px(120))
name Population Area, mi2 Density, persons / sq mi
Toronto 2,794,356 244 11,468
Ottawa 1,017,449 1,077 945
Mississauga 717,961 113 6,352
Brampton 656,480 103 6,395
Hamilton 569,353 432 1,319
London 422,324 162 2,601
Markham 338,503 81 4,156
Vaughan 323,103 105 3,072
Kitchener 256,885 53 4,863
Windsor 229,660 56 4,074

It’s possible to start with an empty table (i.e., no columns and no rows) and add one or more columns to that. You can, for example, use dplyr::tibble() or data.frame() to create a completely empty table. The first cols_add() call for an empty table can have columns of arbitrary length but subsequent uses of cols_add() must adhere to the rule of new columns being the same length as existing.

dplyr::tibble() |>
  gt() |>
  cols_add(
    num = 1:5,
    chr = vec_fmt_spelled_num(1:5)
  )
num chr
1 one
2 two
3 three
4 four
5 five

Tables can contain no rows, yet have columns. In the following example, we’ll create a zero-row table with three columns (num, chr, and ext) and perform the same cols_add()-based addition of two columns of data. This is another case where the function allows for arbitrary-length columns (since always adding zero-length columns is impractical). Furthermore, here we can reference columns that already exist (num and chr) and add values to them.

dplyr::tibble(
  num = numeric(0),
  chr = character(0),
  ext = character(0)
) |>
  gt() |>
  cols_add(
    num = 1:5,
    chr = vec_fmt_spelled_num(1:5)
  )
num chr ext
1 one NA
2 two NA
3 three NA
4 four NA
5 five NA

We should note that the ext column did not receive any values from cols_add() but the table was expanded to having five rows nonetheless. So, each cell of ext was by necessity filled with an NA value.