08-3: Making Tables with gt

Tips to make the most of the lecture notes

Transcript

The usual two navigation tricks: the stacked lines bottom left for a table of contents, and the letter o for a panel view of every slide. This deck has three animated walkthroughs in it, each stepping through one long pipeline a line at a time, and each taking up a good number of slides. If you are hunting for a particular function rather than watching an animation, the table of contents is much faster than arrowing through. You can come back to the animations once you know what you are looking for.

  • Click on the three horizontally stacked lines at the bottom left corner of the slide, then you will see table of contents, and you can jump to the section you want

  • Hit letter “o” on your keyboard and you will have a panel view of all the slides

Transcript

The code boxes work as usual: blue area is an editor, Run Code runs it, copy button takes it to your machine. As with the flextable deck, almost every table you see here was built when the slides were rendered, on my machine, rather than in your browser. A gt table is a block of HTML, and that does not come back through browser R as a table. So treat the code here as something to copy into RStudio rather than something to run in place. The genuinely live cells on this deck are the help pages. If you do use a live blue code area, selecting only part of the code and pressing Command plus Enter on a Mac, or Control plus Enter on Windows, runs just that selection. The two-sheets icon copies the whole chunk, while the reload icon immediately to its left restores the original code after you experiment. Those controls let you test a small change without losing the worked example you started from. One more, at the right end of the toolbar: the eye icon hides that cell’s output and a second click brings it back. Some of these results run long, and once you have read one it is just pushing the rest of the slide out of view.

  • The box area with a hint of blue as the background color is where you can write code (hereafter referred to as the “code area”).
  • Hit the “Run Code” button to execute all the code inside the code area.
  • You can evaluate (run) code selectively by highlighting the parts you want to run and hitting Command + Enter for Mac (Ctrl + Enter for Windows).
  • If you want to run the codes on your computer, you can first click on the icon with two sheets of paper stacked on top of each other (top right corner of the code chunk), which copies the code in the code area. You can then paste it onto your computer.
  • You can click on the reload button (top right corner of the code chunk, left to the copy button) to revert back to the original code.
  • Click the eye icon to hide a code area’s output, and click it again to bring it back. It sits at the right end of the toolbar, next to the copy button, or on the Output banner when the output is shown beside the code. Useful when a long result pushes the rest of the slide out of view.

Create tables with the gt package


Taste of the gt package

tab_data
# A tibble: 10 × 7
   country_name     region        y_1995   y_2005   y_2015 pop_ratio_05_15 date 
   <chr>            <chr>          <int>    <int>    <int>           <dbl> <chr>
 1 Australia        Australasia 18004882 20176844 23815995            1.18 2013…
 2 New Zealand      Australasia  3673400  4133900  4609400            1.12 2013…
 3 Papua New Guinea Melanesia    4616439  6498818  8682174            1.34 2013…
 4 Solomon Islands  Melanesia     375189   482486   612660            1.27 2013…
 5 Vanuatu          Melanesia     170612   217632   276438            1.27 2013…
 6 New Caledonia    Melanesia     193816   232250   269460            1.16 2013…
 7 French Polynesia Polynesia     231446   271060   291787            1.08 2013…
 8 Samoa            Polynesia     174902   188626   203571            1.08 2013…
 9 Tonga            Polynesia      99977   105633   106122            1.00 2013…
10 Tuvalu           Polynesia       9585     9912    10877            1.10 2013…

Taste of the gt package

tab_data %>%
  dplyr::select(country_name, region, y_1995, y_2005, pop_ratio_05_15)
# A tibble: 10 × 5
   country_name     region        y_1995   y_2005 pop_ratio_05_15
   <chr>            <chr>          <int>    <int>           <dbl>
 1 Australia        Australasia 18004882 20176844            1.18
 2 New Zealand      Australasia  3673400  4133900            1.12
 3 Papua New Guinea Melanesia    4616439  6498818            1.34
 4 Solomon Islands  Melanesia     375189   482486            1.27
 5 Vanuatu          Melanesia     170612   217632            1.27
 6 New Caledonia    Melanesia     193816   232250            1.16
 7 French Polynesia Polynesia     231446   271060            1.08
 8 Samoa            Polynesia     174902   188626            1.08
 9 Tonga            Polynesia      99977   105633            1.00
10 Tuvalu           Polynesia       9585     9912            1.10

Taste of the gt package

tab_data %>%
  dplyr::select(country_name, region, y_1995, y_2005, pop_ratio_05_15) %>%
  gt(rowname_col = "country_name", groupname_col = "region")
y_1995 y_2005 pop_ratio_05_15
Australasia
Australia 18004882 20176844 1.180363
New Zealand 3673400 4133900 1.115025
Melanesia
Papua New Guinea 4616439 6498818 1.335962
Solomon Islands 375189 482486 1.269799
Vanuatu 170612 217632 1.270208
New Caledonia 193816 232250 1.160215
Polynesia
French Polynesia 231446 271060 1.076466
Samoa 174902 188626 1.079231
Tonga 99977 105633 1.004629
Tuvalu 9585 9912 1.097357

Taste of the gt package

tab_data %>%
  dplyr::select(country_name, region, y_1995, y_2005, pop_ratio_05_15) %>%
  gt(rowname_col = "country_name", groupname_col = "region") %>%
  tab_header(
    title = md("**Population of selected Pacific countries**"),
    subtitle = "1995 and 2005"
  )
Population of selected Pacific countries
1995 and 2005
y_1995 y_2005 pop_ratio_05_15
Australasia
Australia 18004882 20176844 1.180363
New Zealand 3673400 4133900 1.115025
Melanesia
Papua New Guinea 4616439 6498818 1.335962
Solomon Islands 375189 482486 1.269799
Vanuatu 170612 217632 1.270208
New Caledonia 193816 232250 1.160215
Polynesia
French Polynesia 231446 271060 1.076466
Samoa 174902 188626 1.079231
Tonga 99977 105633 1.004629
Tuvalu 9585 9912 1.097357

Taste of the gt package

tab_data %>%
  dplyr::select(country_name, region, y_1995, y_2005, pop_ratio_05_15) %>%
  gt(rowname_col = "country_name", groupname_col = "region") %>%
  tab_header(
    title = md("**Population of selected Pacific countries**"),
    subtitle = "1995 and 2005"
  ) %>%
  fmt_number(columns = c(y_1995, y_2005), decimals = 0)
Population of selected Pacific countries
1995 and 2005
y_1995 y_2005 pop_ratio_05_15
Australasia
Australia 18,004,882 20,176,844 1.180363
New Zealand 3,673,400 4,133,900 1.115025
Melanesia
Papua New Guinea 4,616,439 6,498,818 1.335962
Solomon Islands 375,189 482,486 1.269799
Vanuatu 170,612 217,632 1.270208
New Caledonia 193,816 232,250 1.160215
Polynesia
French Polynesia 231,446 271,060 1.076466
Samoa 174,902 188,626 1.079231
Tonga 99,977 105,633 1.004629
Tuvalu 9,585 9,912 1.097357

Taste of the gt package

tab_data %>%
  dplyr::select(country_name, region, y_1995, y_2005, pop_ratio_05_15) %>%
  gt(rowname_col = "country_name", groupname_col = "region") %>%
  tab_header(
    title = md("**Population of selected Pacific countries**"),
    subtitle = "1995 and 2005"
  ) %>%
  fmt_number(columns = c(y_1995, y_2005), decimals = 0) %>%
  fmt_percent(columns = pop_ratio_05_15, decimals = 0)
Population of selected Pacific countries
1995 and 2005
y_1995 y_2005 pop_ratio_05_15
Australasia
Australia 18,004,882 20,176,844 118%
New Zealand 3,673,400 4,133,900 112%
Melanesia
Papua New Guinea 4,616,439 6,498,818 134%
Solomon Islands 375,189 482,486 127%
Vanuatu 170,612 217,632 127%
New Caledonia 193,816 232,250 116%
Polynesia
French Polynesia 231,446 271,060 108%
Samoa 174,902 188,626 108%
Tonga 99,977 105,633 100%
Tuvalu 9,585 9,912 110%

Taste of the gt package

tab_data %>%
  dplyr::select(country_name, region, y_1995, y_2005, pop_ratio_05_15) %>%
  gt(rowname_col = "country_name", groupname_col = "region") %>%
  tab_header(
    title = md("**Population of selected Pacific countries**"),
    subtitle = "1995 and 2005"
  ) %>%
  fmt_number(columns = c(y_1995, y_2005), decimals = 0) %>%
  fmt_percent(columns = pop_ratio_05_15, decimals = 0) %>%
  cols_label(
    y_1995 = "1995",
    y_2005 = "2005",
    pop_ratio_05_15 = "2015 vs 2005"
  )
Population of selected Pacific countries
1995 and 2005
1995 2005 2015 vs 2005
Australasia
Australia 18,004,882 20,176,844 118%
New Zealand 3,673,400 4,133,900 112%
Melanesia
Papua New Guinea 4,616,439 6,498,818 134%
Solomon Islands 375,189 482,486 127%
Vanuatu 170,612 217,632 127%
New Caledonia 193,816 232,250 116%
Polynesia
French Polynesia 231,446 271,060 108%
Samoa 174,902 188,626 108%
Tonga 99,977 105,633 100%
Tuvalu 9,585 9,912 110%

Taste of the gt package

tab_data %>%
  dplyr::select(country_name, region, y_1995, y_2005, pop_ratio_05_15) %>%
  gt(rowname_col = "country_name", groupname_col = "region") %>%
  tab_header(
    title = md("**Population of selected Pacific countries**"),
    subtitle = "1995 and 2005"
  ) %>%
  fmt_number(columns = c(y_1995, y_2005), decimals = 0) %>%
  fmt_percent(columns = pop_ratio_05_15, decimals = 0) %>%
  cols_label(
    y_1995 = "1995",
    y_2005 = "2005",
    pop_ratio_05_15 = "2015 vs 2005"
  ) %>%
  tab_spanner(label = "Population", columns = c(y_1995, y_2005))
Population of selected Pacific countries
1995 and 2005
Population
2015 vs 2005
1995 2005
Australasia
Australia 18,004,882 20,176,844 118%
New Zealand 3,673,400 4,133,900 112%
Melanesia
Papua New Guinea 4,616,439 6,498,818 134%
Solomon Islands 375,189 482,486 127%
Vanuatu 170,612 217,632 127%
New Caledonia 193,816 232,250 116%
Polynesia
French Polynesia 231,446 271,060 108%
Samoa 174,902 188,626 108%
Tonga 99,977 105,633 100%
Tuvalu 9,585 9,912 110%

Taste of the gt package

tab_data %>%
  dplyr::select(country_name, region, y_1995, y_2005, pop_ratio_05_15) %>%
  gt(rowname_col = "country_name", groupname_col = "region") %>%
  tab_header(
    title = md("**Population of selected Pacific countries**"),
    subtitle = "1995 and 2005"
  ) %>%
  fmt_number(columns = c(y_1995, y_2005), decimals = 0) %>%
  fmt_percent(columns = pop_ratio_05_15, decimals = 0) %>%
  cols_label(
    y_1995 = "1995",
    y_2005 = "2005",
    pop_ratio_05_15 = "2015 vs 2005"
  ) %>%
  tab_spanner(label = "Population", columns = c(y_1995, y_2005)) %>%
  tab_style(
    style = cell_text(weight = "bold"),
    locations = cells_column_labels()
  )
Population of selected Pacific countries
1995 and 2005
Population
2015 vs 2005
1995 2005
Australasia
Australia 18,004,882 20,176,844 118%
New Zealand 3,673,400 4,133,900 112%
Melanesia
Papua New Guinea 4,616,439 6,498,818 134%
Solomon Islands 375,189 482,486 127%
Vanuatu 170,612 217,632 127%
New Caledonia 193,816 232,250 116%
Polynesia
French Polynesia 231,446 271,060 108%
Samoa 174,902 188,626 108%
Tonga 99,977 105,633 100%
Tuvalu 9,585 9,912 110%

Taste of the gt package

tab_data %>%
  dplyr::select(country_name, region, y_1995, y_2005, pop_ratio_05_15) %>%
  gt(rowname_col = "country_name", groupname_col = "region") %>%
  tab_header(
    title = md("**Population of selected Pacific countries**"),
    subtitle = "1995 and 2005"
  ) %>%
  fmt_number(columns = c(y_1995, y_2005), decimals = 0) %>%
  fmt_percent(columns = pop_ratio_05_15, decimals = 0) %>%
  cols_label(
    y_1995 = "1995",
    y_2005 = "2005",
    pop_ratio_05_15 = "2015 vs 2005"
  ) %>%
  tab_spanner(label = "Population", columns = c(y_1995, y_2005)) %>%
  tab_style(
    style = cell_text(weight = "bold"),
    locations = cells_column_labels()
  ) %>%
  tab_style(
    style = cell_fill(color = "#fdf1d8"),
    locations = cells_body(rows = y_2005 > 2e5)
  )
Population of selected Pacific countries
1995 and 2005
Population
2015 vs 2005
1995 2005
Australasia
Australia 18,004,882 20,176,844 118%
New Zealand 3,673,400 4,133,900 112%
Melanesia
Papua New Guinea 4,616,439 6,498,818 134%
Solomon Islands 375,189 482,486 127%
Vanuatu 170,612 217,632 127%
New Caledonia 193,816 232,250 116%
Polynesia
French Polynesia 231,446 271,060 108%
Samoa 174,902 188,626 108%
Tonga 99,977 105,633 100%
Tuvalu 9,585 9,912 110%

Taste of the gt package

tab_data %>%
  dplyr::select(country_name, region, y_1995, y_2005, pop_ratio_05_15) %>%
  gt(rowname_col = "country_name", groupname_col = "region") %>%
  tab_header(
    title = md("**Population of selected Pacific countries**"),
    subtitle = "1995 and 2005"
  ) %>%
  fmt_number(columns = c(y_1995, y_2005), decimals = 0) %>%
  fmt_percent(columns = pop_ratio_05_15, decimals = 0) %>%
  cols_label(
    y_1995 = "1995",
    y_2005 = "2005",
    pop_ratio_05_15 = "2015 vs 2005"
  ) %>%
  tab_spanner(label = "Population", columns = c(y_1995, y_2005)) %>%
  tab_style(
    style = cell_text(weight = "bold"),
    locations = cells_column_labels()
  ) %>%
  tab_style(
    style = cell_fill(color = "#fdf1d8"),
    locations = cells_body(rows = y_2005 > 2e5)
  ) %>%
  data_color(columns = pop_ratio_05_15, palette = c("white", "#C90000"))
Population of selected Pacific countries
1995 and 2005
Population
2015 vs 2005
1995 2005
Australasia
Australia 18,004,882 20,176,844 118%
New Zealand 3,673,400 4,133,900 112%
Melanesia
Papua New Guinea 4,616,439 6,498,818 134%
Solomon Islands 375,189 482,486 127%
Vanuatu 170,612 217,632 127%
New Caledonia 193,816 232,250 116%
Polynesia
French Polynesia 231,446 271,060 108%
Samoa 174,902 188,626 108%
Tonga 99,977 105,633 100%
Tuvalu 9,585 9,912 110%

Taste of the gt package

tab_data %>%
  dplyr::select(country_name, region, y_1995, y_2005, pop_ratio_05_15) %>%
  gt(rowname_col = "country_name", groupname_col = "region") %>%
  tab_header(
    title = md("**Population of selected Pacific countries**"),
    subtitle = "1995 and 2005"
  ) %>%
  fmt_number(columns = c(y_1995, y_2005), decimals = 0) %>%
  fmt_percent(columns = pop_ratio_05_15, decimals = 0) %>%
  cols_label(
    y_1995 = "1995",
    y_2005 = "2005",
    pop_ratio_05_15 = "2015 vs 2005"
  ) %>%
  tab_spanner(label = "Population", columns = c(y_1995, y_2005)) %>%
  tab_style(
    style = cell_text(weight = "bold"),
    locations = cells_column_labels()
  ) %>%
  tab_style(
    style = cell_fill(color = "#fdf1d8"),
    locations = cells_body(rows = y_2005 > 2e5)
  ) %>%
  data_color(columns = pop_ratio_05_15, palette = c("white", "#C90000")) %>%
  tab_footnote(
    footnote = "2015 population divided by 2005 population.",
    locations = cells_column_labels(columns = pop_ratio_05_15)
  )
Population of selected Pacific countries
1995 and 2005
Population
2015 vs 20051
1995 2005
Australasia
Australia 18,004,882 20,176,844 118%
New Zealand 3,673,400 4,133,900 112%
Melanesia
Papua New Guinea 4,616,439 6,498,818 134%
Solomon Islands 375,189 482,486 127%
Vanuatu 170,612 217,632 127%
New Caledonia 193,816 232,250 116%
Polynesia
French Polynesia 231,446 271,060 108%
Samoa 174,902 188,626 108%
Tonga 99,977 105,633 100%
Tuvalu 9,585 9,912 110%
1 2015 population divided by 2005 population.

Taste of the gt package

tab_data %>%
  dplyr::select(country_name, region, y_1995, y_2005, pop_ratio_05_15) %>%
  gt(rowname_col = "country_name", groupname_col = "region") %>%
  tab_header(
    title = md("**Population of selected Pacific countries**"),
    subtitle = "1995 and 2005"
  ) %>%
  fmt_number(columns = c(y_1995, y_2005), decimals = 0) %>%
  fmt_percent(columns = pop_ratio_05_15, decimals = 0) %>%
  cols_label(
    y_1995 = "1995",
    y_2005 = "2005",
    pop_ratio_05_15 = "2015 vs 2005"
  ) %>%
  tab_spanner(label = "Population", columns = c(y_1995, y_2005)) %>%
  tab_style(
    style = cell_text(weight = "bold"),
    locations = cells_column_labels()
  ) %>%
  tab_style(
    style = cell_fill(color = "#fdf1d8"),
    locations = cells_body(rows = y_2005 > 2e5)
  ) %>%
  data_color(columns = pop_ratio_05_15, palette = c("white", "#C90000")) %>%
  tab_footnote(
    footnote = "2015 population divided by 2005 population.",
    locations = cells_column_labels(columns = pop_ratio_05_15)
  ) %>%
  tab_source_note(source_note = md("Source: `countrypops` in the **gt** package."))
Population of selected Pacific countries
1995 and 2005
Population
2015 vs 20051
1995 2005
Australasia
Australia 18,004,882 20,176,844 118%
New Zealand 3,673,400 4,133,900 112%
Melanesia
Papua New Guinea 4,616,439 6,498,818 134%
Solomon Islands 375,189 482,486 127%
Vanuatu 170,612 217,632 127%
New Caledonia 193,816 232,250 116%
Polynesia
French Polynesia 231,446 271,060 108%
Samoa 174,902 188,626 108%
Tonga 99,977 105,633 100%
Tuvalu 9,585 9,912 110%
1 2015 population divided by 2005 population.
Source: countrypops in the gt package.

Taste of the gt package

tab_data %>%
  dplyr::select(country_name, region, y_1995, y_2005, pop_ratio_05_15) %>%
  gt(rowname_col = "country_name", groupname_col = "region") %>%
  tab_header(
    title = md("**Population of selected Pacific countries**"),
    subtitle = "1995 and 2005"
  ) %>%
  fmt_number(columns = c(y_1995, y_2005), decimals = 0) %>%
  fmt_percent(columns = pop_ratio_05_15, decimals = 0) %>%
  cols_label(
    y_1995 = "1995",
    y_2005 = "2005",
    pop_ratio_05_15 = "2015 vs 2005"
  ) %>%
  tab_spanner(label = "Population", columns = c(y_1995, y_2005)) %>%
  tab_style(
    style = cell_text(weight = "bold"),
    locations = cells_column_labels()
  ) %>%
  tab_style(
    style = cell_fill(color = "#fdf1d8"),
    locations = cells_body(rows = y_2005 > 2e5)
  ) %>%
  data_color(columns = pop_ratio_05_15, palette = c("white", "#C90000")) %>%
  tab_footnote(
    footnote = "2015 population divided by 2005 population.",
    locations = cells_column_labels(columns = pop_ratio_05_15)
  ) %>%
  tab_source_note(source_note = md("Source: `countrypops` in the **gt** package.")) %>%
  opt_row_striping()
Population of selected Pacific countries
1995 and 2005
Population
2015 vs 20051
1995 2005
Australasia
Australia 18,004,882 20,176,844 118%
New Zealand 3,673,400 4,133,900 112%
Melanesia
Papua New Guinea 4,616,439 6,498,818 134%
Solomon Islands 375,189 482,486 127%
Vanuatu 170,612 217,632 127%
New Caledonia 193,816 232,250 116%
Polynesia
French Polynesia 231,446 271,060 108%
Samoa 174,902 188,626 108%
Tonga 99,977 105,633 100%
Tuvalu 9,585 9,912 110%
1 2015 population divided by 2005 population.
Source: countrypops in the gt package.

Getting started

Transcript

One package to install, and no companion package this time. Everything gt needs is inside gt itself, which is one practical difference from flextable, where the fp underscore functions you reach for constantly live in officer. The name stands for grammar of tables, and that is the claim being made: that a table has parts, and that you build one by naming a part and saying what goes there. gt is developed by Posit, the same people who make RStudio and the tidyverse, so the argument conventions will feel familiar. The two lines on screen have different jobs. Install packages downloads gt and normally needs to be run only once on a computer. Library gt attaches the installed package for the current R session, so that is the line you run again when you start a new session and want to use functions such as gt and tab style.

Install the following package and library it.

#--- install if you have not ---#
install.packages("gt")

#--- library ---#
library(gt)


gt stands for grammar of tables. Unlike flextable, it does not need a companion package: officer is to flextable what nothing at all is to gt.

Transcript

The same dataset the flextable deck used, so you can hold the two side by side and compare how each package does the same job. It comes from countrypops in the gt package, filtered to ten Pacific and Australasian countries and three years, then pivoted so each year becomes its own column. Ten rows, small enough to see whole on a slide. The region column built with case when matters here more than it did before, because gt can turn a column like that into row groups, which is something flextable has no direct equivalent for. Read the preparation pipeline from top to bottom. The three character vectors collect the two-letter country codes into Australasia, Melanesia, and Polynesia. The first filter keeps codes belonging to any of those vectors, and the second keeps only nineteen ninety-five, two thousand five, and two thousand fifteen. Case when translates each code into its region label. Pivot wider takes population as the cell values, takes year as the new column names, and adds the y underscore prefix, producing y underscore nineteen ninety-five, y underscore two thousand five, and y underscore two thousand fifteen. Arrange then puts regions together and orders countries within each region from the largest two-thousand-fifteen population downward. Select removes every remaining column whose name starts with country code. The final mutate creates the two-thousand-fifteen to two-thousand-five population ratio used in the percentage examples and a date value used later to demonstrate date formatting. The parentheses around the assignment make R both save tab data and print it, so you can inspect the prepared rows immediately.

#--- Define regions ---#
Australasia <- c("AU", "NZ")
Melanesia <- c("NC", "PG", "SB", "VU")
Polynesia <- c("PF", "WS", "TO", "TV")

#--- create a dataset ---#
(
  tab_data <-
    countrypops %>%
    dplyr::filter(country_code_2 %in% c(
      Australasia, Melanesia, Polynesia
    )) %>%
    dplyr::filter(year %in% c(1995, 2005, 2015)) %>%
    mutate(region = case_when(
      country_code_2 %in% Australasia ~ "Australasia",
      country_code_2 %in% Melanesia ~ "Melanesia",
      country_code_2 %in% Polynesia ~ "Polynesia",
    )) %>%
    pivot_wider(
      values_from = population,
      names_from = year,
      names_prefix = "y_"
    ) %>%
    dplyr::arrange(region, desc(y_2015)) %>%
    dplyr::select(-starts_with("country_code")) %>%
    mutate(
      pop_ratio_05_15 = y_2015 / y_2005,
      date = "2013-11-14"
    )
)
# A tibble: 10 × 7
   country_name     region        y_1995   y_2005   y_2015 pop_ratio_05_15 date 
   <chr>            <chr>          <int>    <int>    <int>           <dbl> <chr>
 1 Australia        Australasia 18004882 20176844 23815995            1.18 2013…
 2 New Zealand      Australasia  3673400  4133900  4609400            1.12 2013…
 3 Papua New Guinea Melanesia    4616439  6498818  8682174            1.34 2013…
 4 Solomon Islands  Melanesia     375189   482486   612660            1.27 2013…
 5 Vanuatu          Melanesia     170612   217632   276438            1.27 2013…
 6 New Caledonia    Melanesia     193816   232250   269460            1.16 2013…
 7 French Polynesia Polynesia     231446   271060   291787            1.08 2013…
 8 Samoa            Polynesia     174902   188626   203571            1.08 2013…
 9 Tonga            Polynesia      99977   105633   106122            1.00 2013…
10 Tuvalu           Polynesia       9585     9912    10877            1.10 2013…
Transcript

Turning a data frame into a gt table is one function call with no arguments needed. Note what is missing compared with flextable: there is no col keys argument, so you cannot pick and order columns in the same call. You select before, with dplyr, or you hide and reorder after, with cols hide and cols move. That is deliberate. gt assumes the data reaching it is already the data you want, and treats column choice as a data question rather than a table question. The pipeline on the left first selects country name, region, and the nineteen-ninety-five and two-thousand-five population columns. Gt then converts exactly those four columns into the table shown on the right. The left chunk is displayed as code without being evaluated on the slide, while the right chunk hides its repeated source and shows the evaluated table, so you can compare the recipe directly with its result.

tab_data %>%
  dplyr::select(
    country_name,
    region,
    y_1995,
    y_2005
  ) %>%
  gt()
country_name region y_1995 y_2005
Australia Australasia 18004882 20176844
New Zealand Australasia 3673400 4133900
Papua New Guinea Melanesia 4616439 6498818
Solomon Islands Melanesia 375189 482486
Vanuatu Melanesia 170612 217632
New Caledonia Melanesia 193816 232250
French Polynesia Polynesia 231446 271060
Samoa Polynesia 174902 188626
Tonga Polynesia 99977 105633
Tuvalu Polynesia 9585 9912

There is no col_keys equivalent. Select the columns you want before gt(), or drop and reorder them after with cols_hide() and cols_move().

The parts of a table

Transcript

This is the list that makes the whole package predictable, so it is worth a minute. A gt table has a header at the top holding a title and subtitle, then column labels which can sit under spanners, then the body, and at the left edge of the body an optional stub holding row names and row group labels. Underneath there can be summary rows, and at the bottom a footer holding footnotes and source notes. Everything gt does is adding something to one of those parts or changing how one of them looks.

A gt table is built out of named parts, and almost every function you will use adds something to a part or changes how a part looks:

  • table header: title and subtitle
  • column labels: the names above the columns, optionally grouped under spanners
  • the stub: the left-hand column of row names, and the row group labels that break the body into blocks
  • the body: the data itself
  • summary rows: totals and averages, per group or for the whole table
  • the footer: footnotes and source notes
Transcript

Learn the prefixes and you can guess most of the package. tab underscore something adds or changes a part of the table. fmt underscore something changes how values are displayed. cols underscore something works on columns. opt underscore something sets a whole-table option, and tab options is the general version of those. cells underscore something names a location rather than doing anything itself. This is genuinely how the package is organised, so when you want to do something new, the first guess should be the prefix, and then autocomplete will usually finish the job.

Function names in gt are prefixed by what they act on:

Prefix What it does Examples
tab_*() add or change a part of the table tab_header(), tab_footnote(), tab_spanner(), tab_style()
fmt_*() change how values are displayed fmt_number(), fmt_percent(), fmt_date()
cols_*() act on columns cols_label(), cols_move(), cols_hide(), cols_width()
cells_*() name a location (does nothing on its own) cells_body(), cells_column_labels(), cells_stub()
opt_*() set a whole-table option opt_row_striping(), opt_stylize()

When you want something new, guess the prefix first and let autocomplete finish it.

Transcript

The stub is the left-hand column that labels the rows rather than holding data, and you create it by naming a column in the rowname col argument. Look at what changes: country name moves out of the data area and into its own column at the left, with no column label above it, and a vertical rule separating it from the numbers. That is the published-table convention. It also changes how you select those cells later, because they are no longer part of the body. Cells stub, not cells body, reaches them.

rowname_col = moves a column into the stub: it labels the rows instead of being data.

tab_data %>%
  dplyr::select(
    country_name, region,
    y_1995, y_2005
  ) %>%
  gt(rowname_col = "country_name")
region y_1995 y_2005
Australia Australasia 18004882 20176844
New Zealand Australasia 3673400 4133900
Papua New Guinea Melanesia 4616439 6498818
Solomon Islands Melanesia 375189 482486
Vanuatu Melanesia 170612 217632
New Caledonia Melanesia 193816 232250
French Polynesia Polynesia 231446 271060
Samoa Polynesia 174902 188626
Tonga Polynesia 99977 105633
Tuvalu Polynesia 9585 9912

Stub cells are no longer part of the body, so cells_stub() reaches them, not cells_body().

Transcript

This is the thing gt does that flextable does not have a direct answer for. Name a column in groupname col and its values become labels that break the body into blocks, with each label on its own row above the rows it covers. In the flextable deck we approximated this with merge v, which collapsed repeated values into one tall cell. This is the other convention, and for grouped rows it is usually the one published tables use. Note that the groups appear in the order the rows are sorted, which is why the data was arranged by region. In this example, rowname col still moves country name into the stub, while groupname col removes region from the ordinary data columns and uses it for the three group headings. The two arguments therefore control different levels of labeling: one identifies each row, and the other identifies the block containing that row.

groupname_col = turns a column into row group labels, which split the body into blocks.

tab_data %>%
  dplyr::select(
    country_name, region,
    y_1995, y_2005
  ) %>%
  gt(
    rowname_col = "country_name",
    groupname_col = "region"
  )
y_1995 y_2005
Australasia
Australia 18004882 20176844
New Zealand 3673400 4133900
Melanesia
Papua New Guinea 4616439 6498818
Solomon Islands 375189 482486
Vanuatu 170612 217632
New Caledonia 193816 232250
Polynesia
French Polynesia 231446 271060
Samoa 174902 188626
Tonga 99977 105633
Tuvalu 9585 9912

This is the gt answer to merge_v() in flextable.

Transcript

A variant worth knowing. Setting row group as column to TRUE puts the group labels in their own column at the left instead of on separate rows above each block. The result looks very much like a merge v table in flextable, so if you are converting a table between the two packages, this is the setting that makes them match. Which of the two you want is a house-style question rather than a technical one. Journals differ, and both are considered correct.

row_group_as_column = TRUE puts group labels in a column of their own instead of on rows above each block. This is what a merge_v() table looks like in flextable.

tab_data %>%
  dplyr::select(
    country_name, region,
    y_1995, y_2005
  ) %>%
  gt(
    rowname_col = "country_name",
    groupname_col = "region",
    row_group_as_column = TRUE
  )
y_1995 y_2005
Australasia Australia 18004882 20176844
New Zealand 3673400 4133900
Melanesia Papua New Guinea 4616439 6498818
Solomon Islands 375189 482486
Vanuatu 170612 217632
New Caledonia 193816 232250
Polynesia French Polynesia 231446 271060
Samoa 174902 188626
Tonga 99977 105633
Tuvalu 9585 9912
Transcript

Groups appear in the order their rows appear in the data, so normally you control the order by sorting before you build the table. When that is inconvenient, row group order takes the labels in the order you want them. Give it every group name, not a subset, or the ones you leave out end up somewhere you did not choose. Sorting the data is usually the cleaner route, because then the order is visible where the data is prepared rather than buried in the table code.

row_group_order() sets the order of the groups directly. Sorting the data before gt() does the same job and is usually clearer.

tab_data %>%
  dplyr::select(
    country_name, region,
    y_1995, y_2005
  ) %>%
  gt(groupname_col = "region") %>%
  row_group_order(
    groups = c(
      "Polynesia",
      "Melanesia",
      "Australasia"
    )
  )
country_name y_1995 y_2005
Polynesia
French Polynesia 231446 271060
Samoa 174902 188626
Tonga 99977 105633
Tuvalu 9585 9912
Melanesia
Papua New Guinea 4616439 6498818
Solomon Islands 375189 482486
Vanuatu 170612 217632
New Caledonia 193816 232250
Australasia
Australia 18004882 20176844
New Zealand 3673400 4133900

Locations

Transcript

This is the one place where gt and flextable really diverge, so slow down here. In flextable you said i for rows and j for columns, and every formatting function took them. In gt you name a location instead, using a cells underscore something function, and hand that to whatever function needs to know where. Cells body is the one you will use most, and it takes columns and rows arguments. The rest of the list names the other parts: the column labels, the stub, the row groups, the title, the summary rows, the footer. The names on screen follow the anatomy you just saw. Cells stub selects row names, cells column labels selects the labels above individual columns, cells column spanners selects the labels spanning several columns, and cells row groups selects the group headings inside the body. Cells title uses its groups argument to distinguish the title from the subtitle. Cells summary and cells grand summary reach the per-group and whole-table summary rows. Cells source notes and cells footnotes reach the two footer areas. None of these changes a table by itself. It returns a location description that you pass through a locations argument to a function such as tab style or tab footnote.

flextable said where with i (rows) and j (columns). gt says where with a cells_*() function:

  • cells_body(columns =, rows =): the data cells
  • cells_stub(rows =): the row names
  • cells_column_labels(columns =): the labels above the columns
  • cells_column_spanners(spanners =): the labels above those
  • cells_row_groups(groups =): the row group labels
  • cells_title(groups = "title"): the title or subtitle
  • cells_summary(), cells_grand_summary(): summary rows
  • cells_source_notes(), cells_footnotes(): the footer

A cells_*() function does nothing on its own. You hand it to a function that needs to be told where, through a locations = argument.

Transcript

This creates gt tbl, the table we build on for most of the rest of the lecture. Four columns, ten rows, no formatting. Same idea as ft in the flextable deck: build it once, then pipe it into different experiments without rebuilding it each time. Every example from here starts from gt tbl and adds one thing, so you can see exactly what each function did. Look at the plain version now so you have a baseline to compare the later slides against.

We will be building on gt_tbl created below:

gt_tbl <-
  tab_data %>%
  dplyr::select(
    country_name,
    region,
    y_1995,
    y_2005
  ) %>%
  gt()
country_name region y_1995 y_2005
Australia Australasia 18004882 20176844
New Zealand Australasia 3673400 4133900
Papua New Guinea Melanesia 4616439 6498818
Solomon Islands Melanesia 375189 482486
Vanuatu Melanesia 170612 217632
New Caledonia Melanesia 193816 232250
French Polynesia Polynesia 231446 271060
Samoa Polynesia 174902 188626
Tonga Polynesia 99977 105633
Tuvalu Polynesia 9585 9912
Transcript

The rows argument accepts a condition written with the column names directly, unquoted, exactly the way you would write it inside dplyr filter. So rows equals y two thousand five greater than two hundred thousand selects the rows where that holds. This is the same idea as the formula form in flextable, and for the same reason it is the one to default to. The condition describes itself, so somebody reading it later sees which rows and why, instead of numbers they have to work out. It also keeps working when the data changes. Now connect that condition to the whole example. Tab style is told to make text red. Cells body limits that change to the country name and region columns, and the rows condition limits it again to countries whose two-thousand-five population exceeds two hundred thousand. The population column supplies the test even though it is not one of the columns being colored. That separation is useful whenever one variable determines how another part of the table should look.

Syntax

cells_body(
  columns = <columns>,
  rows = <condition using the column names>
)


Example

gt_tbl %>%
  tab_style(
    style = cell_text(color = "red"),
    locations = cells_body(
      columns = c(country_name, region),
      rows = y_2005 > 2e5
    )
  )
country_name region y_1995 y_2005
Australia Australasia 18004882 20176844
New Zealand Australasia 3673400 4133900
Papua New Guinea Melanesia 4616439 6498818
Solomon Islands Melanesia 375189 482486
Vanuatu Melanesia 170612 217632
New Caledonia Melanesia 193816 232250
French Polynesia Polynesia 231446 271060
Samoa Polynesia 174902 188626
Tonga Polynesia 99977 105633
Tuvalu Polynesia 9585 9912
Transcript

The same job with row numbers, and with a vector of TRUEs and FALSEs. Both work, and the logical vector has to be exactly as long as the table has rows, which is why the example builds ten values for a ten-row table. Hard-coded row numbers are the risky form. They break silently when your data changes, because there will still be a row three, it will just be a different country. Use them when you genuinely mean the third row, and use a condition whenever you mean a row that satisfies something. The first tab style call fills the country-name cells in row two and rows four through nine with a light gray background. The second call selects columns one and three by position and italicizes the rows chosen by the logical vector. Rep with each equal to five produces five TRUE values followed by five FALSE values, so only the first half of the table receives that second style. Because the calls are piped one after the other, both sets of formatting remain in the final table, and cells where their selections overlap get both effects.

gt_tbl %>%
  tab_style(
    style = cell_fill(color = "grey90"),
    locations = cells_body(
      columns = country_name,
      rows = c(2, 4:9)
    )
  ) %>%
  tab_style(
    style = cell_text(style = "italic"),
    locations = cells_body(
      columns = c(1, 3),
      rows = rep(c(TRUE, FALSE), each = 5)
    )
  )
country_name region y_1995 y_2005
Australia Australasia 18004882 20176844
New Zealand Australasia 3673400 4133900
Papua New Guinea Melanesia 4616439 6498818
Solomon Islands Melanesia 375189 482486
Vanuatu Melanesia 170612 217632
New Caledonia Melanesia 193816 232250
French Polynesia Polynesia 231446 271060
Samoa Polynesia 174902 188626
Tonga Polynesia 99977 105633
Tuvalu Polynesia 9585 9912
Transcript

The columns argument takes the same selection language dplyr select takes, which is more than flextable’s j ever offered. Bare names, c of several names, numbers, and the helpers: starts with, ends with, contains, where, everything. The example uses starts with y underscore to catch both year columns without naming them, which keeps working if you add another year to the data later. That is the argument for the helpers generally. A selection that describes a pattern survives changes to the data, and a list of names does not. Here, cell fill supplies the pale cream color and cells body applies it to every body column whose original name begins with y underscore. Country name and region are left alone. Notice that tidyselect belongs in the columns argument, while the rows argument still uses row positions, logical values, or data conditions. Keeping those two selection jobs distinct makes a complicated location easier to read.

columns = accepts anything dplyr::select() accepts: bare names, numbers, and helpers like starts_with(), ends_with(), contains(), where(), everything().

gt_tbl %>%
  tab_style(
    style = cell_fill(color = "#fdf1d8"),
    locations = cells_body(
      columns = starts_with("y_")
    )
  )
country_name region y_1995 y_2005
Australia Australasia 18004882 20176844
New Zealand Australasia 3673400 4133900
Papua New Guinea Melanesia 4616439 6498818
Solomon Islands Melanesia 375189 482486
Vanuatu Melanesia 170612 217632
New Caledonia Melanesia 193816 232250
French Polynesia Polynesia 231446 271060
Samoa Polynesia 174902 188626
Tonga Polynesia 99977 105633
Tuvalu Polynesia 9585 9912
Transcript

When the same change applies in more than one part of the table, wrap the locations in a list rather than repeating the call. The example makes the column labels and one column of the body bold in a single step. This is worth knowing because it is the answer to a question the flextable deck handled with the part argument. gt has no part equals all. Instead you list the parts you mean, which is more typing but leaves no doubt about which parts were included.

There is no part = "all" in gt. List the locations you mean instead.

gt_tbl %>%
  tab_style(
    style = cell_text(weight = "bold"),
    locations = list(
      cells_column_labels(),
      cells_body(columns = country_name)
    )
  )
country_name region y_1995 y_2005
Australia Australasia 18004882 20176844
New Zealand Australasia 3673400 4133900
Papua New Guinea Melanesia 4616439 6498818
Solomon Islands Melanesia 375189 482486
Vanuatu Melanesia 170612 217632
New Caledonia Melanesia 193816 232250
French Polynesia Polynesia 231446 271060
Samoa Polynesia 174902 188626
Tonga Polynesia 99977 105633
Tuvalu Polynesia 9585 9912

Style

Transcript

One function does all the styling in gt, and its shape mirrors the style function in flextable closely. You say what to change with the style argument and where with the locations argument. The what comes from one of three functions: cell text for the characters, cell fill for the background, cell borders for the lines. Notice how much smaller this is than the flextable equivalent, which needed fp text, fp par and fp cell from officer, and a paragraph-versus-cell distinction on top. gt has no paragraph layer at all. The data argument at the start is normally supplied by the pipe. Cell text can control color, size, weight, italics, alignment, and font; cell fill controls the background; and cell borders controls the lines around the selected cells. If several of those changes belong at the same location, the style argument can take a list of style functions. The locations argument then receives one cells function, or a list of locations when the same style should appear in several table parts.

tab_style() does all the styling.

Syntax

tab_style(
  data,
  style = <what to change>,
  locations = <where>
)


The style = argument takes one of these, or a list() of them:

  • cell_text(): color, size, weight, style, alignment, font
  • cell_fill(): background color
  • cell_borders(): borders around the selected cells

There is no paragraph layer here. flextable distinguished paragraphs from cells and needed fp_par() and fp_cell() for the two. gt has only cells.

Transcript

The first of the three, and the one you reach for most. Cell text controls everything about the characters: color, size, weight, italics, alignment, the font itself. Note that alignment lives here, which is a real difference from flextable, where alignment was a paragraph property because text sat inside a paragraph inside a cell. gt has no paragraph, so alignment is simply part of the text. The help page is worth opening once, because there are more arguments than you would guess and you will look them up every time anyway. Use the Introduction tab to run the live question-mark cell and inspect those arguments. Then move to Example. There, tab style makes the country names in rows four through six red, bold, and underlined. Color, weight, and decorate each contribute one visible part of that result, while cells body supplies both the country-name column and the three-row range. The output on the right lets you verify that no other rows or columns changed.

cell_text() changes the appearance of the characters themselves.


Syntax

gt_tbl %>%
  tab_style(
    style = cell_text(
      color = "red",
      weight = "bold",
      decorate = "underline"
    ),
    locations = cells_body(
      columns = country_name,
      rows = 4:6
    )
  )
country_name region y_1995 y_2005
Australia Australasia 18004882 20176844
New Zealand Australasia 3673400 4133900
Papua New Guinea Melanesia 4616439 6498818
Solomon Islands Melanesia 375189 482486
Vanuatu Melanesia 170612 217632
New Caledonia Melanesia 193816 232250
French Polynesia Polynesia 231446 271060
Samoa Polynesia 174902 188626
Tonga Polynesia 99977 105633
Tuvalu Polynesia 9585 9912
Transcript

The background color of the selected cells, and it takes a color and optionally an alpha value between zero and one for transparency. The example shades the region cells of the smaller countries, using a condition on a column that is not the one being shaded, which is a pattern you will use constantly. Where the shading goes and what decides the shading are separate questions, and gt keeps them separate: columns says where, rows says which, and neither has to be the column you are looking at.

cell_fill() sets the background color of the selected cells. alpha = between 0 and 1 makes it transparent.


Syntax

gt_tbl %>%
  tab_style(
    style = cell_fill(
      color = "grey",
      alpha = 0.5
    ),
    locations = cells_body(
      columns = region,
      rows = y_2005 < 2e5
    )
  )
country_name region y_1995 y_2005
Australia Australasia 18004882 20176844
New Zealand Australasia 3673400 4133900
Papua New Guinea Melanesia 4616439 6498818
Solomon Islands Melanesia 375189 482486
Vanuatu Melanesia 170612 217632
New Caledonia Melanesia 193816 232250
French Polynesia Polynesia 231446 271060
Samoa Polynesia 174902 188626
Tonga Polynesia 99977 105633
Tuvalu Polynesia 9585 9912
Transcript

Borders in gt are one function rather than the dozen flextable had. You say which sides, in what color, what weight and what style, and where. Sides accepts all, or any combination of top, bottom, left and right. Weight takes a pixel value through the px helper, and getting that wrong fails quietly. Write a bare two rather than px of two and there is no error at all: the number reaches the HTML with no unit on it, the browser ignores the whole declaration, and you get the default border width instead of the one you asked for. The example draws a thick red dotted line under row three, which is the same table this deck’s flextable counterpart drew with hline.

cell_borders() draws borders. sides = accepts "all" or any of "top", "bottom", "left", "right".


Syntax


Note

Give weight = a size with units: px(2), not 2. A bare number reaches the HTML as border-bottom-width: 2, which the browser ignores, so you silently get the default border rather than the one you asked for.

gt_tbl %>%
  tab_style(
    style = cell_borders(
      sides = "bottom",
      color = "red",
      weight = px(4),
      style = "dotted"
    ),
    locations = cells_body(rows = 3)
  )
country_name region y_1995 y_2005
Australia Australasia 18004882 20176844
New Zealand Australasia 3673400 4133900
Papua New Guinea Melanesia 4616439 6498818
Solomon Islands Melanesia 375189 482486
Vanuatu Melanesia 170612 217632
New Caledonia Melanesia 193816 232250
French Polynesia Polynesia 231446 271060
Samoa Polynesia 174902 188626
Tonga Polynesia 99977 105633
Tuvalu Polynesia 9585 9912
Transcript

When you want more than one kind of change in the same place, pass a list of style functions instead of one. The example fills the column labels dark red and makes the text on them white and bold, which takes one call rather than three. This is the everyday shape of gt styling code: a pipeline where each step names one place and everything that should be true about it. If a table comes out looking wrong, comment out one tab style call at a time, which is much the fastest way to find which one did it.

gt_tbl %>%
  tab_style(
    style = list(
      cell_fill(color = "#C90000"),
      cell_text(
        color = "white",
        weight = "bold"
      )
    ),
    locations = cells_column_labels()
  )
country_name region y_1995 y_2005
Australia Australasia 18004882 20176844
New Zealand Australasia 3673400 4133900
Papua New Guinea Melanesia 4616439 6498818
Solomon Islands Melanesia 375189 482486
Vanuatu Melanesia 170612 217632
New Caledonia Melanesia 193816 232250
French Polynesia Polynesia 231446 271060
Samoa Polynesia 174902 188626
Tonga Polynesia 99977 105633
Tuvalu Polynesia 9585 9912

Demonstration: Styling

tab_data
# A tibble: 10 × 7
   country_name     region        y_1995   y_2005   y_2015 pop_ratio_05_15 date 
   <chr>            <chr>          <int>    <int>    <int>           <dbl> <chr>
 1 Australia        Australasia 18004882 20176844 23815995            1.18 2013…
 2 New Zealand      Australasia  3673400  4133900  4609400            1.12 2013…
 3 Papua New Guinea Melanesia    4616439  6498818  8682174            1.34 2013…
 4 Solomon Islands  Melanesia     375189   482486   612660            1.27 2013…
 5 Vanuatu          Melanesia     170612   217632   276438            1.27 2013…
 6 New Caledonia    Melanesia     193816   232250   269460            1.16 2013…
 7 French Polynesia Polynesia     231446   271060   291787            1.08 2013…
 8 Samoa            Polynesia     174902   188626   203571            1.08 2013…
 9 Tonga            Polynesia      99977   105633   106122            1.00 2013…
10 Tuvalu           Polynesia       9585     9912    10877            1.10 2013…

Demonstration: Styling

tab_data %>%
  dplyr::select(country_name, region, y_1995, y_2005)
# A tibble: 10 × 4
   country_name     region        y_1995   y_2005
   <chr>            <chr>          <int>    <int>
 1 Australia        Australasia 18004882 20176844
 2 New Zealand      Australasia  3673400  4133900
 3 Papua New Guinea Melanesia    4616439  6498818
 4 Solomon Islands  Melanesia     375189   482486
 5 Vanuatu          Melanesia     170612   217632
 6 New Caledonia    Melanesia     193816   232250
 7 French Polynesia Polynesia     231446   271060
 8 Samoa            Polynesia     174902   188626
 9 Tonga            Polynesia      99977   105633
10 Tuvalu           Polynesia       9585     9912

Demonstration: Styling

tab_data %>%
  dplyr::select(country_name, region, y_1995, y_2005) %>%
  gt()
country_name region y_1995 y_2005
Australia Australasia 18004882 20176844
New Zealand Australasia 3673400 4133900
Papua New Guinea Melanesia 4616439 6498818
Solomon Islands Melanesia 375189 482486
Vanuatu Melanesia 170612 217632
New Caledonia Melanesia 193816 232250
French Polynesia Polynesia 231446 271060
Samoa Polynesia 174902 188626
Tonga Polynesia 99977 105633
Tuvalu Polynesia 9585 9912

Demonstration: Styling

tab_data %>%
  dplyr::select(country_name, region, y_1995, y_2005) %>%
  gt() %>%
#--- text color ---#
  tab_style(
    style = cell_text(color = "#fcba03"),
    locations = cells_body(columns = region, rows = 1)
  )
country_name region y_1995 y_2005
Australia Australasia 18004882 20176844
New Zealand Australasia 3673400 4133900
Papua New Guinea Melanesia 4616439 6498818
Solomon Islands Melanesia 375189 482486
Vanuatu Melanesia 170612 217632
New Caledonia Melanesia 193816 232250
French Polynesia Polynesia 231446 271060
Samoa Polynesia 174902 188626
Tonga Polynesia 99977 105633
Tuvalu Polynesia 9585 9912

Demonstration: Styling

tab_data %>%
  dplyr::select(country_name, region, y_1995, y_2005) %>%
  gt() %>%
#--- text color ---#
  tab_style(
    style = cell_text(color = "#fcba03"),
    locations = cells_body(columns = region, rows = 1)
  ) %>%
#--- background ---#
  tab_style(
    style = cell_fill(color = "grey"),
    locations = cells_body(columns = region, rows = y_2005 < 2e5)
  )
country_name region y_1995 y_2005
Australia Australasia 18004882 20176844
New Zealand Australasia 3673400 4133900
Papua New Guinea Melanesia 4616439 6498818
Solomon Islands Melanesia 375189 482486
Vanuatu Melanesia 170612 217632
New Caledonia Melanesia 193816 232250
French Polynesia Polynesia 231446 271060
Samoa Polynesia 174902 188626
Tonga Polynesia 99977 105633
Tuvalu Polynesia 9585 9912

Demonstration: Styling

tab_data %>%
  dplyr::select(country_name, region, y_1995, y_2005) %>%
  gt() %>%
#--- text color ---#
  tab_style(
    style = cell_text(color = "#fcba03"),
    locations = cells_body(columns = region, rows = 1)
  ) %>%
#--- background ---#
  tab_style(
    style = cell_fill(color = "grey"),
    locations = cells_body(columns = region, rows = y_2005 < 2e5)
  ) %>%
#--- font type ---#
  tab_style(
    style = cell_text(font = "Times New Roman"),
    locations = cells_body(columns = c(country_name, y_2005), rows = 5)
  )
country_name region y_1995 y_2005
Australia Australasia 18004882 20176844
New Zealand Australasia 3673400 4133900
Papua New Guinea Melanesia 4616439 6498818
Solomon Islands Melanesia 375189 482486
Vanuatu Melanesia 170612 217632
New Caledonia Melanesia 193816 232250
French Polynesia Polynesia 231446 271060
Samoa Polynesia 174902 188626
Tonga Polynesia 99977 105633
Tuvalu Polynesia 9585 9912

Demonstration: Styling

tab_data %>%
  dplyr::select(country_name, region, y_1995, y_2005) %>%
  gt() %>%
#--- text color ---#
  tab_style(
    style = cell_text(color = "#fcba03"),
    locations = cells_body(columns = region, rows = 1)
  ) %>%
#--- background ---#
  tab_style(
    style = cell_fill(color = "grey"),
    locations = cells_body(columns = region, rows = y_2005 < 2e5)
  ) %>%
#--- font type ---#
  tab_style(
    style = cell_text(font = "Times New Roman"),
    locations = cells_body(columns = c(country_name, y_2005), rows = 5)
  ) %>%
#--- font size ---#
  tab_style(
    style = cell_text(size = px(20)),
    locations = cells_body(rows = 7)
  )
country_name region y_1995 y_2005
Australia Australasia 18004882 20176844
New Zealand Australasia 3673400 4133900
Papua New Guinea Melanesia 4616439 6498818
Solomon Islands Melanesia 375189 482486
Vanuatu Melanesia 170612 217632
New Caledonia Melanesia 193816 232250
French Polynesia Polynesia 231446 271060
Samoa Polynesia 174902 188626
Tonga Polynesia 99977 105633
Tuvalu Polynesia 9585 9912

Demonstration: Styling

tab_data %>%
  dplyr::select(country_name, region, y_1995, y_2005) %>%
  gt() %>%
#--- text color ---#
  tab_style(
    style = cell_text(color = "#fcba03"),
    locations = cells_body(columns = region, rows = 1)
  ) %>%
#--- background ---#
  tab_style(
    style = cell_fill(color = "grey"),
    locations = cells_body(columns = region, rows = y_2005 < 2e5)
  ) %>%
#--- font type ---#
  tab_style(
    style = cell_text(font = "Times New Roman"),
    locations = cells_body(columns = c(country_name, y_2005), rows = 5)
  ) %>%
#--- font size ---#
  tab_style(
    style = cell_text(size = px(20)),
    locations = cells_body(rows = 7)
  ) %>%
#--- italicize ---#
  tab_style(
    style = cell_text(style = "italic"),
    locations = cells_body(columns = region)
  )
country_name region y_1995 y_2005
Australia Australasia 18004882 20176844
New Zealand Australasia 3673400 4133900
Papua New Guinea Melanesia 4616439 6498818
Solomon Islands Melanesia 375189 482486
Vanuatu Melanesia 170612 217632
New Caledonia Melanesia 193816 232250
French Polynesia Polynesia 231446 271060
Samoa Polynesia 174902 188626
Tonga Polynesia 99977 105633
Tuvalu Polynesia 9585 9912

Demonstration: Styling

tab_data %>%
  dplyr::select(country_name, region, y_1995, y_2005) %>%
  gt() %>%
#--- text color ---#
  tab_style(
    style = cell_text(color = "#fcba03"),
    locations = cells_body(columns = region, rows = 1)
  ) %>%
#--- background ---#
  tab_style(
    style = cell_fill(color = "grey"),
    locations = cells_body(columns = region, rows = y_2005 < 2e5)
  ) %>%
#--- font type ---#
  tab_style(
    style = cell_text(font = "Times New Roman"),
    locations = cells_body(columns = c(country_name, y_2005), rows = 5)
  ) %>%
#--- font size ---#
  tab_style(
    style = cell_text(size = px(20)),
    locations = cells_body(rows = 7)
  ) %>%
#--- italicize ---#
  tab_style(
    style = cell_text(style = "italic"),
    locations = cells_body(columns = region)
  ) %>%
#--- bold ---#
  tab_style(
    style = cell_text(weight = "bold"),
    locations = cells_body(columns = y_2005)
  )
country_name region y_1995 y_2005
Australia Australasia 18004882 20176844
New Zealand Australasia 3673400 4133900
Papua New Guinea Melanesia 4616439 6498818
Solomon Islands Melanesia 375189 482486
Vanuatu Melanesia 170612 217632
New Caledonia Melanesia 193816 232250
French Polynesia Polynesia 231446 271060
Samoa Polynesia 174902 188626
Tonga Polynesia 99977 105633
Tuvalu Polynesia 9585 9912

Demonstration: Styling

tab_data %>%
  dplyr::select(country_name, region, y_1995, y_2005) %>%
  gt() %>%
#--- text color ---#
  tab_style(
    style = cell_text(color = "#fcba03"),
    locations = cells_body(columns = region, rows = 1)
  ) %>%
#--- background ---#
  tab_style(
    style = cell_fill(color = "grey"),
    locations = cells_body(columns = region, rows = y_2005 < 2e5)
  ) %>%
#--- font type ---#
  tab_style(
    style = cell_text(font = "Times New Roman"),
    locations = cells_body(columns = c(country_name, y_2005), rows = 5)
  ) %>%
#--- font size ---#
  tab_style(
    style = cell_text(size = px(20)),
    locations = cells_body(rows = 7)
  ) %>%
#--- italicize ---#
  tab_style(
    style = cell_text(style = "italic"),
    locations = cells_body(columns = region)
  ) %>%
#--- bold ---#
  tab_style(
    style = cell_text(weight = "bold"),
    locations = cells_body(columns = y_2005)
  ) %>%
#--- vertical alignment ---#
  tab_style(
    style = cell_text(v_align = "top"),
    locations = cells_body(columns = y_2005, rows = region == "Australasia")
  )
country_name region y_1995 y_2005
Australia Australasia 18004882 20176844
New Zealand Australasia 3673400 4133900
Papua New Guinea Melanesia 4616439 6498818
Solomon Islands Melanesia 375189 482486
Vanuatu Melanesia 170612 217632
New Caledonia Melanesia 193816 232250
French Polynesia Polynesia 231446 271060
Samoa Polynesia 174902 188626
Tonga Polynesia 99977 105633
Tuvalu Polynesia 9585 9912

Demonstration: Styling

tab_data %>%
  dplyr::select(country_name, region, y_1995, y_2005) %>%
  gt() %>%
#--- text color ---#
  tab_style(
    style = cell_text(color = "#fcba03"),
    locations = cells_body(columns = region, rows = 1)
  ) %>%
#--- background ---#
  tab_style(
    style = cell_fill(color = "grey"),
    locations = cells_body(columns = region, rows = y_2005 < 2e5)
  ) %>%
#--- font type ---#
  tab_style(
    style = cell_text(font = "Times New Roman"),
    locations = cells_body(columns = c(country_name, y_2005), rows = 5)
  ) %>%
#--- font size ---#
  tab_style(
    style = cell_text(size = px(20)),
    locations = cells_body(rows = 7)
  ) %>%
#--- italicize ---#
  tab_style(
    style = cell_text(style = "italic"),
    locations = cells_body(columns = region)
  ) %>%
#--- bold ---#
  tab_style(
    style = cell_text(weight = "bold"),
    locations = cells_body(columns = y_2005)
  ) %>%
#--- vertical alignment ---#
  tab_style(
    style = cell_text(v_align = "top"),
    locations = cells_body(columns = y_2005, rows = region == "Australasia")
  ) %>%
#--- borders ---#
  tab_style(
    style = cell_borders(sides = "all", color = "black", weight = px(1)),
    locations = cells_body()
  )
country_name region y_1995 y_2005
Australia Australasia 18004882 20176844
New Zealand Australasia 3673400 4133900
Papua New Guinea Melanesia 4616439 6498818
Solomon Islands Melanesia 375189 482486
Vanuatu Melanesia 170612 217632
New Caledonia Melanesia 193816 232250
French Polynesia Polynesia 231446 271060
Samoa Polynesia 174902 188626
Tonga Polynesia 99977 105633
Tuvalu Polynesia 9585 9912

Demonstration: Styling

tab_data %>%
  dplyr::select(country_name, region, y_1995, y_2005) %>%
  gt() %>%
#--- text color ---#
  tab_style(
    style = cell_text(color = "#fcba03"),
    locations = cells_body(columns = region, rows = 1)
  ) %>%
#--- background ---#
  tab_style(
    style = cell_fill(color = "grey"),
    locations = cells_body(columns = region, rows = y_2005 < 2e5)
  ) %>%
#--- font type ---#
  tab_style(
    style = cell_text(font = "Times New Roman"),
    locations = cells_body(columns = c(country_name, y_2005), rows = 5)
  ) %>%
#--- font size ---#
  tab_style(
    style = cell_text(size = px(20)),
    locations = cells_body(rows = 7)
  ) %>%
#--- italicize ---#
  tab_style(
    style = cell_text(style = "italic"),
    locations = cells_body(columns = region)
  ) %>%
#--- bold ---#
  tab_style(
    style = cell_text(weight = "bold"),
    locations = cells_body(columns = y_2005)
  ) %>%
#--- vertical alignment ---#
  tab_style(
    style = cell_text(v_align = "top"),
    locations = cells_body(columns = y_2005, rows = region == "Australasia")
  ) %>%
#--- borders ---#
  tab_style(
    style = cell_borders(sides = "all", color = "black", weight = px(1)),
    locations = cells_body()
  ) %>%
#--- the column labels ---#
  tab_style(
    style = list(cell_fill(color = "#C90000"), cell_text(color = "white")),
    locations = cells_column_labels()
  )
country_name region y_1995 y_2005
Australia Australasia 18004882 20176844
New Zealand Australasia 3673400 4133900
Papua New Guinea Melanesia 4616439 6498818
Solomon Islands Melanesia 375189 482486
Vanuatu Melanesia 170612 217632
New Caledonia Melanesia 193816 232250
French Polynesia Polynesia 231446 271060
Samoa Polynesia 174902 188626
Tonga Polynesia 99977 105633
Tuvalu Polynesia 9585 9912

Formatting values

Transcript

This is the part of gt with no real counterpart in what we covered for flextable, and it is the reason many people prefer gt for numbers. The fmt functions change how a value is displayed without changing the value. So after you have formatted a population column with thousands separators, you can still select rows with a condition on the raw number, because the raw number is still there. Formatting is a display layer over the data. That property is what lets you format early in a pipeline and keep working with the real values afterwards. The families on screen cover more than ordinary decimals. Number and integer formatting handle separators, decimal places, and suffixes; percent, currency, and scientific formatting add the conventions for those quantities; and date, datetime, and time formatting control temporal displays. Markdown, URL, and image formatting turn stored text into richer table content. Sub missing and sub zero replace an N A or a zero with a more readable display without rewriting the underlying data. Every one of these functions accepts columns and rows, so the same selection ideas from the Locations section let you format only the cells that need it.

The fmt_*() functions change how values are displayed. They do not change the values, so conditions like rows = y_2005 > 2e5 still work on the raw numbers afterwards.

  • fmt_number(), fmt_integer(): decimals, thousands separators, suffixes
  • fmt_percent(), fmt_currency(), fmt_scientific()
  • fmt_date(), fmt_datetime(), fmt_time()
  • fmt_markdown(), fmt_url(), fmt_image()
  • sub_missing(), sub_zero(): replace NA and zero with something readable

Each takes columns = and rows =, so you can format part of a column.

Transcript

The workhorse. Decimals says how many places, and use seps puts in the thousands separators, which is on by default and is most of why you would call this. Compare the two columns on this slide with the unformatted table earlier: nine million is far easier to read as nine comma something than as a run of digits. There is a locale argument too, which switches the separator and decimal marks to another country’s convention, and that is worth remembering if you ever publish to a European journal.

gt_tbl %>%
  fmt_number(
    columns = c(y_1995, y_2005),
    decimals = 0,
    use_seps = TRUE
  )
country_name region y_1995 y_2005
Australia Australasia 18,004,882 20,176,844
New Zealand Australasia 3,673,400 4,133,900
Papua New Guinea Melanesia 4,616,439 6,498,818
Solomon Islands Melanesia 375,189 482,486
Vanuatu Melanesia 170,612 217,632
New Caledonia Melanesia 193,816 232,250
French Polynesia Polynesia 231,446 271,060
Samoa Polynesia 174,902 188,626
Tonga Polynesia 99,977 105,633
Tuvalu Polynesia 9,585 9,912
Transcript

For whole numbers, and its interesting argument is suffixing. Turn it on and large numbers are shortened with a K for thousands and an M for millions, so eighteen million something becomes eighteen M. Use fmt number with suffixing set to true and n sigfig set to three when you want a result such as eighteen point one M. Whether you want that depends entirely on your audience. It reads well on a slide, where the point is the comparison rather than the exact count. It reads badly in a table somebody might need to take numbers out of, because you have thrown away the digits they need.

gt_tbl %>%
  fmt_integer(
    columns = c(y_1995, y_2005),
    suffixing = TRUE
  )
country_name region y_1995 y_2005
Australia Australasia 18M 20M
New Zealand Australasia 4M 4M
Papua New Guinea Melanesia 5M 6M
Solomon Islands Melanesia 375K 482K
Vanuatu Melanesia 171K 218K
New Caledonia Melanesia 194K 232K
French Polynesia Polynesia 231K 271K
Samoa Polynesia 175K 189K
Tonga Polynesia 100K 106K
Tuvalu Polynesia 10K 10K
Transcript

Two more, on a table that includes the ratio column and the date column so there is something to format. Fmt percent multiplies by a hundred and appends the sign, so a ratio of one point one three shows as a hundred and thirteen percent. Note that it multiplies, so give it a proportion and not a number that is already a percentage. Fmt date takes a date style, either by name or by number, and there are a lot of them. The help page prints the full list with an example of each, which is quicker than guessing. The select call keeps only country name, the population ratio, and date before gt builds the table. In fmt percent, decimals equal to one keeps one digit after the decimal point in the displayed percentage. In fmt date, the w d, m, day, year style turns the stored two-thousand-thirteen hyphen eleven hyphen fourteen value into a label with the abbreviated weekday and month followed by the day and year. Both formatting calls change presentation only, so the stored ratio and date remain available for later conditions or calculations.

tab_data %>%
  dplyr::select(
    country_name,
    pop_ratio_05_15,
    date
  ) %>%
  gt() %>%
  fmt_percent(
    columns = pop_ratio_05_15,
    decimals = 1
  ) %>%
  fmt_date(
    columns = date,
    date_style = "wd_m_day_year"
  )
country_name pop_ratio_05_15 date
Australia 118.0% Thu, Nov 14, 2013
New Zealand 111.5% Thu, Nov 14, 2013
Papua New Guinea 133.6% Thu, Nov 14, 2013
Solomon Islands 127.0% Thu, Nov 14, 2013
Vanuatu 127.0% Thu, Nov 14, 2013
New Caledonia 116.0% Thu, Nov 14, 2013
French Polynesia 107.6% Thu, Nov 14, 2013
Samoa 107.9% Thu, Nov 14, 2013
Tonga 100.5% Thu, Nov 14, 2013
Tuvalu 109.7% Thu, Nov 14, 2013

fmt_percent() multiplies by 100, so hand it a proportion rather than a number that is already a percentage.

Transcript

The rows argument works inside the fmt functions exactly as it did inside cells body, which means you can format part of a column differently from the rest. The example gives the Melanesian rows two decimal places and leaves the others alone. This sounds like a strange thing to want until you have a table mixing quantities of very different sizes in one column, where a single number of decimal places is either too many for the large values or too few for the small ones.

gt_tbl %>%
  fmt_number(
    columns = y_1995,
    rows = region == "Melanesia",
    decimals = 2
  )
country_name region y_1995 y_2005
Australia Australasia 18004882 20176844
New Zealand Australasia 3673400 4133900
Papua New Guinea Melanesia 4,616,439.00 6498818
Solomon Islands Melanesia 375,189.00 482486
Vanuatu Melanesia 170,612.00 217632
New Caledonia Melanesia 193,816.00 232250
French Polynesia Polynesia 231446 271060
Samoa Polynesia 174902 188626
Tonga Polynesia 99977 105633
Tuvalu Polynesia 9585 9912

Columns

Transcript

Column labels default to your variable names, which are written for typing rather than for reading. Cols label renames them, taking the existing column name on the left and the label you want on the right. The label can be plain text, or you can wrap it in md for markdown, which is how you get bold or italic or a subscript into a header. As in flextable, this changes only what is displayed. Later code still refers to y underscore nineteen ninety five, not to the pretty label, so rename late or keep selecting by the original name. The other wrapper named on screen is html, which lets a label contain trusted HTML when the output supports it. In the example, country name becomes Country, region becomes Region, and the two year variables become bold nineteen ninety-five and two thousand five through md. The mapping is existing variable on the left, displayed label on the right. That is why every later selector still uses the original underscored names.

cols_label() renames the displayed labels. Wrap a label in md() for markdown, or html() for HTML.

gt_tbl %>%
  cols_label(
    country_name = "Country",
    region = "Region",
    y_1995 = md("**1995**"),
    y_2005 = md("**2005**")
  )
Country Region 1995 2005
Australia Australasia 18004882 20176844
New Zealand Australasia 3673400 4133900
Papua New Guinea Melanesia 4616439 6498818
Solomon Islands Melanesia 375189 482486
Vanuatu Melanesia 170612 217632
New Caledonia Melanesia 193816 232250
French Polynesia Polynesia 231446 271060
Samoa Polynesia 174902 188626
Tonga Polynesia 99977 105633
Tuvalu Polynesia 9585 9912

Selectors keep using the original column names, not the new labels.

Transcript

This is where the missing col keys argument comes back. Cols move takes columns and puts them after, or before, another column, and there are cols move to start and cols move to end for the two common cases. Cols hide drops a column from the display while leaving it in the data, which matters more than it sounds, because a hidden column can still be used in a condition. So you can hide the region column and still write rows equals region equals Melanesia. That is not possible in flextable, where a column left out of col keys is simply gone. Follow the example in pipeline order. Cols move takes region and places it after y underscore two thousand five, changing the visible order without changing the underlying data. Cols hide then removes y underscore nineteen ninety-five from the display. The output therefore shows country name, y underscore two thousand five, and region, but the hidden nineteen-ninety-five values can still drive a later condition such as greater than one hundred thousand.

gt_tbl %>%
  cols_move(
    columns = region,
    after = y_2005
  ) %>%
  cols_hide(columns = y_1995)
country_name y_2005 region
Australia 20176844 Australasia
New Zealand 4133900 Australasia
Papua New Guinea 6498818 Melanesia
Solomon Islands 482486 Melanesia
Vanuatu 217632 Melanesia
New Caledonia 232250 Melanesia
French Polynesia 271060 Polynesia
Samoa 188626 Polynesia
Tonga 105633 Polynesia
Tuvalu 9912 Polynesia

A hidden column is still in the data, so rows = y_1995 > 1e5 keeps working after cols_hide(columns = y_1995).

Transcript

Widths and alignment. Cols width uses a two-sided formula, with the columns on the left and the width on the right. Use px for pixels or pct for a percentage of the table to be explicit, although a bare number is accepted and treated as pixels. The everything on the last line catches whatever you did not name, which is a good habit, because a table with some widths set and others not can lay out unpredictably. Cols align is simpler and takes a direction and some columns. Note gt has no autofit. It sizes columns to their content by default and you override only where you need to. In this table, country name gets one hundred fifty pixels, region gets one hundred twenty, and everything not already matched gets ninety, which means both year columns. Cols align then centers the displayed values in the two year columns. The widths govern how much horizontal space the cells receive, while alignment governs where their contents sit inside that space, so these are separate operations even when they target the same columns.

gt_tbl %>%
  cols_width(
    country_name ~ px(150),
    region ~ px(120),
    everything() ~ px(90)
  ) %>%
  cols_align(
    align = "center",
    columns = c(y_1995, y_2005)
  )
country_name region y_1995 y_2005
Australia Australasia 18004882 20176844
New Zealand Australasia 3673400 4133900
Papua New Guinea Melanesia 4616439 6498818
Solomon Islands Melanesia 375189 482486
Vanuatu Melanesia 170612 217632
New Caledonia Melanesia 193816 232250
French Polynesia Polynesia 231446 271060
Samoa Polynesia 174902 188626
Tonga Polynesia 99977 105633
Tuvalu Polynesia 9585 9912

There is no autofit() in gt: columns size to their content unless you say otherwise.

Transcript

Putting two columns into one cell, with a pattern saying how they combine. The numbers in curly braces refer to the columns in the order you listed them, so one space open bracket two close bracket puts the second value in parentheses after the first. The second column then disappears from the display. This is how published tables show an estimate with its standard error underneath or beside it, and it is worth remembering when you get to regression tables, because it is the same idea modelsummary uses. The first step formats both year columns with zero decimal places so the strings being merged are readable population counts. Cols merge lists y underscore two thousand five first and y underscore nineteen ninety-five second, so placeholder one is the two-thousand-five value and placeholder two is the nineteen-ninety-five value in parentheses. The merged result keeps the first column’s identity, which is why cols label renames y underscore two thousand five to two thousand five open parenthesis nineteen ninety-five close parenthesis. Y underscore nineteen ninety-five is then absent as a separate displayed column.

gt_tbl %>%
  fmt_number(
    columns = c(y_1995, y_2005),
    decimals = 0
  ) %>%
  cols_merge(
    columns = c(y_2005, y_1995),
    pattern = "{1} ({2})"
  ) %>%
  cols_label(y_2005 = "2005 (1995)")
country_name region 2005 (1995)
Australia Australasia 20,176,844 (18,004,882)
New Zealand Australasia 4,133,900 (3,673,400)
Papua New Guinea Melanesia 6,498,818 (4,616,439)
Solomon Islands Melanesia 482,486 (375,189)
Vanuatu Melanesia 217,632 (170,612)
New Caledonia Melanesia 232,250 (193,816)
French Polynesia Polynesia 271,060 (231,446)
Samoa Polynesia 188,626 (174,902)
Tonga Polynesia 105,633 (99,977)
Tuvalu Polynesia 9,912 (9,585)

{1} and {2} refer to the columns in the order you listed them. This is how an estimate and its standard error end up in one cell.

Spanners

Transcript

A spanner is a label sitting above several column labels, grouping them. Give it a label and the columns it covers, and gt draws the rule under it for you. This is the same table the flextable deck built with add header row and colwidths, and the difference is worth noticing. There you counted how many columns each label spanned. Here you name the columns, so the label stays over the right ones even if you reorder the table later. Spanners can be stacked, so a second call over a group that includes a spanner puts a third row above.

A spanner is a label above several column labels. Name the columns rather than counting them, which is what add_header_row() in flextable made you do.

gt_tbl %>%
  tab_spanner(
    label = "Population",
    columns = c(y_1995, y_2005)
  ) %>%
  cols_label(
    y_1995 = "1995",
    y_2005 = "2005"
  )
country_name region
Population
1995 2005
Australia Australasia 18004882 20176844
New Zealand Australasia 3673400 4133900
Papua New Guinea Melanesia 4616439 6498818
Solomon Islands Melanesia 375189 482486
Vanuatu Melanesia 170612 217632
New Caledonia Melanesia 193816 232250
French Polynesia Polynesia 231446 271060
Samoa Polynesia 174902 188626
Tonga Polynesia 99977 105633
Tuvalu Polynesia 9585 9912
Transcript

A shortcut worth knowing if your column names carry structure. Give it a separator, and gt splits every column name on that separator and turns the first piece into a spanner and the second into the label. Our columns are called y underscore nineteen ninety five and y underscore two thousand five, so splitting on the underscore produces a y spanner over labels of nineteen ninety five and two thousand five. This is exactly the shape pivot wider leaves behind when it builds names with a prefix, so the two functions pair well. The shortcut applies to every selected name containing the delimiter, not just the year variables. Country underscore name is also split, so the output has a country spanner over a name label as well as the y spanner over the two year labels. That is a reason to inspect the result and, when necessary, rename unrelated columns before calling tab spanner delim or select only names whose shared structure you actually want to expose.

tab_spanner_delim() splits column names on a separator and builds the spanner from the first piece. Names left behind by pivot_wider() often have this shape already.

tab_data %>%
  dplyr::select(
    country_name,
    y_1995,
    y_2005
  ) %>%
  gt() %>%
  tab_spanner_delim(delim = "_")
country
y
name 1995 2005
Australia 18004882 20176844
New Zealand 3673400 4133900
Papua New Guinea 4616439 6498818
Solomon Islands 375189 482486
Vanuatu 170612 217632
New Caledonia 193816 232250
French Polynesia 231446 271060
Samoa 174902 188626
Tonga 99977 105633
Tuvalu 9585 9912

Summary rows

Transcript

Totals and averages per row group, computed by gt rather than by you. It needs row groups for there to be groups to summarise, but if the table does not already have a stub, summary rows creates one for the labels. Fns takes a named list where the name becomes the label and the right-hand side is a formula, with the dot standing for the column being summarised. Fmt says how to display the results, and it is a separate argument because summary rows are not formatted by the fmt calls you applied to the body. The setup makes country name the stub and region the grouping column, so each region receives its own Total and Average rows. Sum and mean are applied column by column to the two numeric year columns, with the dot standing for the current column’s values. The names Total and Average become the visible stub labels for those calculated rows. The fmt formula then passes each summary result to fmt number with zero decimal places, giving readable whole-population summaries without altering how the body cells are formatted.

summary_rows() adds a summary row to each row group. It requires row groups, but if the table does not already have a stub, it creates one for the summary labels. Called on a table with no row groups, it is an error, and grand_summary_rows() is the function you want instead.

tab_data %>%
  dplyr::select(
    country_name, region,
    y_1995, y_2005
  ) %>%
  gt(
    rowname_col = "country_name",
    groupname_col = "region"
  ) %>%
  summary_rows(
    fns = list(
      Total = ~ sum(.),
      Average = ~ mean(.)
    ),
    fmt = ~ fmt_number(., decimals = 0)
  )
y_1995 y_2005
Australasia
Australia 18004882 20176844
New Zealand 3673400 4133900
Total 21,678,282 24,310,744
Average 10,839,141 12,155,372
Melanesia
Papua New Guinea 4616439 6498818
Solomon Islands 375189 482486
Vanuatu 170612 217632
New Caledonia 193816 232250
Total 5,356,056 7,431,186
Average 1,339,014 1,857,796
Polynesia
French Polynesia 231446 271060
Samoa 174902 188626
Tonga 99977 105633
Tuvalu 9585 9912
Total 515,910 575,231
Average 128,978 143,808

Summary rows are not covered by the fmt_*() calls you applied to the body, which is why fmt = is a separate argument.

Transcript

The same idea for the table as a whole rather than per group, and it appears at the bottom below everything else. You can use both together, which gives you a total per region and then a total across all regions, which is the standard shape of a published summary table. Note that it works without row groups, so a plain table can have a grand total even with nothing to group by. Here the table still uses country name as the stub and region for its row groups, but grand summary rows ignores those group boundaries when it calculates. The named function applies sum to each numeric year column across all ten countries, and the backticked name Grand total becomes the visible label containing a space. As on the previous tab, the separate fmt formula displays those totals with no decimal places because body formatting does not automatically carry into summary areas.

tab_data %>%
  dplyr::select(
    country_name, region,
    y_1995, y_2005
  ) %>%
  gt(
    rowname_col = "country_name",
    groupname_col = "region"
  ) %>%
  grand_summary_rows(
    fns = list(`Grand total` = ~ sum(.)),
    fmt = ~ fmt_number(., decimals = 0)
  )
y_1995 y_2005
Australasia
Australia 18004882 20176844
New Zealand 3673400 4133900
Melanesia
Papua New Guinea 4616439 6498818
Solomon Islands 375189 482486
Vanuatu 170612 217632
New Caledonia 193816 232250
Polynesia
French Polynesia 231446 271060
Samoa 174902 188626
Tonga 99977 105633
Tuvalu 9585 9912
Grand total 27,550,248 32,317,161

Color from the data

Transcript

Shading cells according to their own values, in one call. Give it columns and a palette, and gt works out the range and maps the colors across it. You can name a palette that ships with the package, or give two or more colors and it interpolates between them. Read the caution though. A colored table is easy to make and easy to overdo, and once every column is shaded the reader has no idea which comparison you wanted them to make. One column shaded in a table of six says look here. Six columns shaded says nothing. The example limits the mapping to y underscore two thousand five. White represents the low end of that column’s observed range, dark red represents the high end, and intermediate values receive interpolated shades. The numbers remain printed in the cells, so color adds a visual comparison rather than replacing the exact values. The callout’s point is about purpose: use the encoding to direct attention to a comparison the reader should make, not merely because the function is available.

data_color() shades cells by their own values.

gt_tbl %>%
  data_color(
    columns = y_2005,
    palette = c("white", "#C90000")
  )
country_name region y_1995 y_2005
Australia Australasia 18004882 20176844
New Zealand Australasia 3673400 4133900
Papua New Guinea Melanesia 4616439 6498818
Solomon Islands Melanesia 375189 482486
Vanuatu Melanesia 170612 217632
New Caledonia Melanesia 193816 232250
French Polynesia Polynesia 231446 271060
Samoa Polynesia 174902 188626
Tonga Polynesia 99977 105633
Tuvalu Polynesia 9585 9912

Note

One shaded column in a table says “look here”. Six shaded columns say nothing.

Transcript

By default the palette is stretched across the range of the values present, which means the same color means different things in two tables built from different data. Setting domain fixes the range, so a value maps to the same color regardless of what else is in the column. If you are producing several tables that a reader will compare, this is not optional. Values outside the domain receive the na color, which is gray by default and can be changed explicitly. In the example, one shared domain from zero to thirty million is applied to both the nineteen-ninety-five and two-thousand-five columns. White marks the low end and dark red the high end for both, so the colors can be compared across years rather than being rescaled separately around each column’s observed values. Choose a domain that has substantive meaning across every table or column you intend readers to compare.

Without domain =, the palette is stretched across whatever values are present, so the same color means different things in two tables. Fix the range when the tables will be compared.

gt_tbl %>%
  data_color(
    columns = c(y_1995, y_2005),
    palette = c("white", "#C90000"),
    domain = c(0, 3e7)
  )
country_name region y_1995 y_2005
Australia Australasia 18004882 20176844
New Zealand Australasia 3673400 4133900
Papua New Guinea Melanesia 4616439 6498818
Solomon Islands Melanesia 375189 482486
Vanuatu Melanesia 170612 217632
New Caledonia Melanesia 193816 232250
French Polynesia Polynesia 231446 271060
Samoa Polynesia 174902 188626
Tonga Polynesia 99977 105633
Tuvalu Polynesia 9585 9912

Whole-table options

Transcript

A finished look in one call. Style takes a number from one to six and color takes one of six names, and between them you get thirty-six ready-made appearances. This is the fastest way to make a table look deliberate rather than default, and it is a reasonable starting point that you then adjust. It is the counterpart of the theme functions in flextable, theme vanilla and the rest. Try a few numbers and pick one, rather than reading about what each does. The call shown here chooses style six and the blue color family, and the output on the right shows the combined preset. These arguments select a coordinated collection of table-wide choices rather than changing only one cell property. Use the preset to establish an overall visual system, then add more specific functions only where the table’s purpose requires them.

gt_tbl %>%
  opt_stylize(style = 6, color = "blue")
country_name region y_1995 y_2005
Australia Australasia 18004882 20176844
New Zealand Australasia 3673400 4133900
Papua New Guinea Melanesia 4616439 6498818
Solomon Islands Melanesia 375189 482486
Vanuatu Melanesia 170612 217632
New Caledonia Melanesia 193816 232250
French Polynesia Polynesia 231446 271060
Samoa Polynesia 174902 188626
Tonga Polynesia 99977 105633
Tuvalu Polynesia 9585 9912

style is 1 to 6 and color is one of six names, so there are 36 ready-made looks. This is the gt counterpart of theme_vanilla() and friends in flextable.

Transcript

Each of these does one thing to the whole table. Row striping shades alternate rows. Table font sets the font everywhere. Align table header moves the title and subtitle. There are more, and they all begin with opt, so autocomplete will show you the list. Reach for these before tab options, because they say what you mean in one argument where tab options would need three. The pipeline first adds Population as a table title so the alignment change has a visible target. Opt row striping turns on alternating row backgrounds, opt table font requests Times New Roman across the table, and opt align table header with left moves the title from its default alignment to the left. Each call returns the table for the next step, so the output combines all four choices.

gt_tbl %>%
  tab_header(title = "Population") %>%
  opt_row_striping() %>%
  opt_table_font(font = "Times New Roman") %>%
  opt_align_table_header(align = "left")
Population
country_name region y_1995 y_2005
Australia Australasia 18004882 20176844
New Zealand Australasia 3673400 4133900
Papua New Guinea Melanesia 4616439 6498818
Solomon Islands Melanesia 375189 482486
Vanuatu Melanesia 170612 217632
New Caledonia Melanesia 193816 232250
French Polynesia Polynesia 231446 271060
Samoa Polynesia 174902 188626
Tonga Polynesia 99977 105633
Tuvalu Polynesia 9585 9912
Transcript

The general version, and it has around two hundred arguments. Do not try to learn them. Learn the naming pattern instead, because the argument names are the part of the table, then a dot, then the property. Table dot font dot size. Column labels dot background dot color. Data row dot padding. Once you see that, you can guess an argument name and let autocomplete confirm it, which is how everyone actually uses this function. The help page lists them all if guessing fails. Read the five examples as part then property. Table dot font dot size sets all table type to fourteen pixels. Column labels dot font dot weight makes the labels bold, and column labels dot background dot color gives that header row a light gray fill. Data row dot padding reduces the space inside each body row to two pixels, making the table more compact. Table dot border dot top dot color makes the top rule red. Pixel helpers matter for the two size arguments because the generated HTML needs explicit units.

gt_tbl %>%
  tab_options(
    table.font.size = px(14),
    column_labels.font.weight = "bold",
    column_labels.background.color = "#f2f2f2",
    data_row.padding = px(2),
    table.border.top.color = "red"
  )
country_name region y_1995 y_2005
Australia Australasia 18004882 20176844
New Zealand Australasia 3673400 4133900
Papua New Guinea Melanesia 4616439 6498818
Solomon Islands Melanesia 375189 482486
Vanuatu Melanesia 170612 217632
New Caledonia Melanesia 193816 232250
French Polynesia Polynesia 231446 271060
Samoa Polynesia 174902 188626
Tonga Polynesia 99977 105633
Tuvalu Polynesia 9585 9912

Argument names are part . property: table.font.size, column_labels.background.color, data_row.padding. Guess the name and let autocomplete confirm it.

Demonstration: A finished table

tab_data
# A tibble: 10 × 7
   country_name     region        y_1995   y_2005   y_2015 pop_ratio_05_15 date 
   <chr>            <chr>          <int>    <int>    <int>           <dbl> <chr>
 1 Australia        Australasia 18004882 20176844 23815995            1.18 2013…
 2 New Zealand      Australasia  3673400  4133900  4609400            1.12 2013…
 3 Papua New Guinea Melanesia    4616439  6498818  8682174            1.34 2013…
 4 Solomon Islands  Melanesia     375189   482486   612660            1.27 2013…
 5 Vanuatu          Melanesia     170612   217632   276438            1.27 2013…
 6 New Caledonia    Melanesia     193816   232250   269460            1.16 2013…
 7 French Polynesia Polynesia     231446   271060   291787            1.08 2013…
 8 Samoa            Polynesia     174902   188626   203571            1.08 2013…
 9 Tonga            Polynesia      99977   105633   106122            1.00 2013…
10 Tuvalu           Polynesia       9585     9912    10877            1.10 2013…

Demonstration: A finished table

tab_data %>%
  dplyr::select(country_name, region, y_1995, y_2005)
# A tibble: 10 × 4
   country_name     region        y_1995   y_2005
   <chr>            <chr>          <int>    <int>
 1 Australia        Australasia 18004882 20176844
 2 New Zealand      Australasia  3673400  4133900
 3 Papua New Guinea Melanesia    4616439  6498818
 4 Solomon Islands  Melanesia     375189   482486
 5 Vanuatu          Melanesia     170612   217632
 6 New Caledonia    Melanesia     193816   232250
 7 French Polynesia Polynesia     231446   271060
 8 Samoa            Polynesia     174902   188626
 9 Tonga            Polynesia      99977   105633
10 Tuvalu           Polynesia       9585     9912

Demonstration: A finished table

tab_data %>%
  dplyr::select(country_name, region, y_1995, y_2005) %>%
  gt(rowname_col = "country_name", groupname_col = "region")
y_1995 y_2005
Australasia
Australia 18004882 20176844
New Zealand 3673400 4133900
Melanesia
Papua New Guinea 4616439 6498818
Solomon Islands 375189 482486
Vanuatu 170612 217632
New Caledonia 193816 232250
Polynesia
French Polynesia 231446 271060
Samoa 174902 188626
Tonga 99977 105633
Tuvalu 9585 9912

Demonstration: A finished table

tab_data %>%
  dplyr::select(country_name, region, y_1995, y_2005) %>%
  gt(rowname_col = "country_name", groupname_col = "region") %>%
#--- format the numbers ---#
  fmt_number(columns = c(y_1995, y_2005), decimals = 0)
y_1995 y_2005
Australasia
Australia 18,004,882 20,176,844
New Zealand 3,673,400 4,133,900
Melanesia
Papua New Guinea 4,616,439 6,498,818
Solomon Islands 375,189 482,486
Vanuatu 170,612 217,632
New Caledonia 193,816 232,250
Polynesia
French Polynesia 231,446 271,060
Samoa 174,902 188,626
Tonga 99,977 105,633
Tuvalu 9,585 9,912

Demonstration: A finished table

tab_data %>%
  dplyr::select(country_name, region, y_1995, y_2005) %>%
  gt(rowname_col = "country_name", groupname_col = "region") %>%
#--- format the numbers ---#
  fmt_number(columns = c(y_1995, y_2005), decimals = 0) %>%
#--- rename the labels ---#
  cols_label(y_1995 = "1995", y_2005 = "2005")
1995 2005
Australasia
Australia 18,004,882 20,176,844
New Zealand 3,673,400 4,133,900
Melanesia
Papua New Guinea 4,616,439 6,498,818
Solomon Islands 375,189 482,486
Vanuatu 170,612 217,632
New Caledonia 193,816 232,250
Polynesia
French Polynesia 231,446 271,060
Samoa 174,902 188,626
Tonga 99,977 105,633
Tuvalu 9,585 9,912

Demonstration: A finished table

tab_data %>%
  dplyr::select(country_name, region, y_1995, y_2005) %>%
  gt(rowname_col = "country_name", groupname_col = "region") %>%
#--- format the numbers ---#
  fmt_number(columns = c(y_1995, y_2005), decimals = 0) %>%
#--- rename the labels ---#
  cols_label(y_1995 = "1995", y_2005 = "2005") %>%
#--- a label above both year columns ---#
  tab_spanner(label = "Population", columns = c(y_1995, y_2005))
Population
1995 2005
Australasia
Australia 18,004,882 20,176,844
New Zealand 3,673,400 4,133,900
Melanesia
Papua New Guinea 4,616,439 6,498,818
Solomon Islands 375,189 482,486
Vanuatu 170,612 217,632
New Caledonia 193,816 232,250
Polynesia
French Polynesia 231,446 271,060
Samoa 174,902 188,626
Tonga 99,977 105,633
Tuvalu 9,585 9,912

Demonstration: A finished table

tab_data %>%
  dplyr::select(country_name, region, y_1995, y_2005) %>%
  gt(rowname_col = "country_name", groupname_col = "region") %>%
#--- format the numbers ---#
  fmt_number(columns = c(y_1995, y_2005), decimals = 0) %>%
#--- rename the labels ---#
  cols_label(y_1995 = "1995", y_2005 = "2005") %>%
#--- a label above both year columns ---#
  tab_spanner(label = "Population", columns = c(y_1995, y_2005)) %>%
#--- a total per region ---#
  summary_rows(
    fns = list(Total = ~ sum(.)),
    fmt = ~ fmt_number(., decimals = 0)
  )
Population
1995 2005
Australasia
Australia 18,004,882 20,176,844
New Zealand 3,673,400 4,133,900
Total 21,678,282 24,310,744
Melanesia
Papua New Guinea 4,616,439 6,498,818
Solomon Islands 375,189 482,486
Vanuatu 170,612 217,632
New Caledonia 193,816 232,250
Total 5,356,056 7,431,186
Polynesia
French Polynesia 231,446 271,060
Samoa 174,902 188,626
Tonga 99,977 105,633
Tuvalu 9,585 9,912
Total 515,910 575,231

Demonstration: A finished table

tab_data %>%
  dplyr::select(country_name, region, y_1995, y_2005) %>%
  gt(rowname_col = "country_name", groupname_col = "region") %>%
#--- format the numbers ---#
  fmt_number(columns = c(y_1995, y_2005), decimals = 0) %>%
#--- rename the labels ---#
  cols_label(y_1995 = "1995", y_2005 = "2005") %>%
#--- a label above both year columns ---#
  tab_spanner(label = "Population", columns = c(y_1995, y_2005)) %>%
#--- a total per region ---#
  summary_rows(
    fns = list(Total = ~ sum(.)),
    fmt = ~ fmt_number(., decimals = 0)
  ) %>%
#--- a ready-made look ---#
  opt_stylize(style = 5, color = "gray")
Population
1995 2005
Australasia
Australia 18,004,882 20,176,844
New Zealand 3,673,400 4,133,900
Total 21,678,282 24,310,744
Melanesia
Papua New Guinea 4,616,439 6,498,818
Solomon Islands 375,189 482,486
Vanuatu 170,612 217,632
New Caledonia 193,816 232,250
Total 5,356,056 7,431,186
Polynesia
French Polynesia 231,446 271,060
Samoa 174,902 188,626
Tonga 99,977 105,633
Tuvalu 9,585 9,912
Total 515,910 575,231

Demonstration: A finished table

tab_data %>%
  dplyr::select(country_name, region, y_1995, y_2005) %>%
  gt(rowname_col = "country_name", groupname_col = "region") %>%
#--- format the numbers ---#
  fmt_number(columns = c(y_1995, y_2005), decimals = 0) %>%
#--- rename the labels ---#
  cols_label(y_1995 = "1995", y_2005 = "2005") %>%
#--- a label above both year columns ---#
  tab_spanner(label = "Population", columns = c(y_1995, y_2005)) %>%
#--- a total per region ---#
  summary_rows(
    fns = list(Total = ~ sum(.)),
    fmt = ~ fmt_number(., decimals = 0)
  ) %>%
#--- a ready-made look ---#
  opt_stylize(style = 5, color = "gray") %>%
#--- alternate row shading ---#
  opt_row_striping()
Population
1995 2005
Australasia
Australia 18,004,882 20,176,844
New Zealand 3,673,400 4,133,900
Total 21,678,282 24,310,744
Melanesia
Papua New Guinea 4,616,439 6,498,818
Solomon Islands 375,189 482,486
Vanuatu 170,612 217,632
New Caledonia 193,816 232,250
Total 5,356,056 7,431,186
Polynesia
French Polynesia 231,446 271,060
Samoa 174,902 188,626
Tonga 99,977 105,633
Tuvalu 9,585 9,912
Total 515,910 575,231

Demonstration: A finished table

tab_data %>%
  dplyr::select(country_name, region, y_1995, y_2005) %>%
  gt(rowname_col = "country_name", groupname_col = "region") %>%
#--- format the numbers ---#
  fmt_number(columns = c(y_1995, y_2005), decimals = 0) %>%
#--- rename the labels ---#
  cols_label(y_1995 = "1995", y_2005 = "2005") %>%
#--- a label above both year columns ---#
  tab_spanner(label = "Population", columns = c(y_1995, y_2005)) %>%
#--- a total per region ---#
  summary_rows(
    fns = list(Total = ~ sum(.)),
    fmt = ~ fmt_number(., decimals = 0)
  ) %>%
#--- a ready-made look ---#
  opt_stylize(style = 5, color = "gray") %>%
#--- alternate row shading ---#
  opt_row_striping() %>%
#--- tighten the rows ---#
  tab_options(data_row.padding = px(2))
Population
1995 2005
Australasia
Australia 18,004,882 20,176,844
New Zealand 3,673,400 4,133,900
Total 21,678,282 24,310,744
Melanesia
Papua New Guinea 4,616,439 6,498,818
Solomon Islands 375,189 482,486
Vanuatu 170,612 217,632
New Caledonia 193,816 232,250
Total 5,356,056 7,431,186
Polynesia
French Polynesia 231,446 271,060
Samoa 174,902 188,626
Tonga 99,977 105,633
Tuvalu 9,585 9,912
Total 515,910 575,231

Demonstration: A finished table

tab_data %>%
  dplyr::select(country_name, region, y_1995, y_2005) %>%
  gt(rowname_col = "country_name", groupname_col = "region") %>%
#--- format the numbers ---#
  fmt_number(columns = c(y_1995, y_2005), decimals = 0) %>%
#--- rename the labels ---#
  cols_label(y_1995 = "1995", y_2005 = "2005") %>%
#--- a label above both year columns ---#
  tab_spanner(label = "Population", columns = c(y_1995, y_2005)) %>%
#--- a total per region ---#
  summary_rows(
    fns = list(Total = ~ sum(.)),
    fmt = ~ fmt_number(., decimals = 0)
  ) %>%
#--- a ready-made look ---#
  opt_stylize(style = 5, color = "gray") %>%
#--- alternate row shading ---#
  opt_row_striping() %>%
#--- tighten the rows ---#
  tab_options(data_row.padding = px(2)) %>%
#--- shrink the type ---#
  tab_options(table.font.size = px(14))
Population
1995 2005
Australasia
Australia 18,004,882 20,176,844
New Zealand 3,673,400 4,133,900
Total 21,678,282 24,310,744
Melanesia
Papua New Guinea 4,616,439 6,498,818
Solomon Islands 375,189 482,486
Vanuatu 170,612 217,632
New Caledonia 193,816 232,250
Total 5,356,056 7,431,186
Polynesia
French Polynesia 231,446 271,060
Samoa 174,902 188,626
Tonga 99,977 105,633
Tuvalu 9,585 9,912
Total 515,910 575,231

Demonstration: A finished table

tab_data %>%
  dplyr::select(country_name, region, y_1995, y_2005) %>%
  gt(rowname_col = "country_name", groupname_col = "region") %>%
#--- format the numbers ---#
  fmt_number(columns = c(y_1995, y_2005), decimals = 0) %>%
#--- rename the labels ---#
  cols_label(y_1995 = "1995", y_2005 = "2005") %>%
#--- a label above both year columns ---#
  tab_spanner(label = "Population", columns = c(y_1995, y_2005)) %>%
#--- a total per region ---#
  summary_rows(
    fns = list(Total = ~ sum(.)),
    fmt = ~ fmt_number(., decimals = 0)
  ) %>%
#--- a ready-made look ---#
  opt_stylize(style = 5, color = "gray") %>%
#--- alternate row shading ---#
  opt_row_striping() %>%
#--- tighten the rows ---#
  tab_options(data_row.padding = px(2)) %>%
#--- shrink the type ---#
  tab_options(table.font.size = px(14)) %>%
#--- a title ---#
  tab_header(title = md("**Population of selected Pacific countries**"))
Population of selected Pacific countries
Population
1995 2005
Australasia
Australia 18,004,882 20,176,844
New Zealand 3,673,400 4,133,900
Total 21,678,282 24,310,744
Melanesia
Papua New Guinea 4,616,439 6,498,818
Solomon Islands 375,189 482,486
Vanuatu 170,612 217,632
New Caledonia 193,816 232,250
Total 5,356,056 7,431,186
Polynesia
French Polynesia 231,446 271,060
Samoa 174,902 188,626
Tonga 99,977 105,633
Tuvalu 9,585 9,912
Total 515,910 575,231

Demonstration: A finished table

tab_data %>%
  dplyr::select(country_name, region, y_1995, y_2005) %>%
  gt(rowname_col = "country_name", groupname_col = "region") %>%
#--- format the numbers ---#
  fmt_number(columns = c(y_1995, y_2005), decimals = 0) %>%
#--- rename the labels ---#
  cols_label(y_1995 = "1995", y_2005 = "2005") %>%
#--- a label above both year columns ---#
  tab_spanner(label = "Population", columns = c(y_1995, y_2005)) %>%
#--- a total per region ---#
  summary_rows(
    fns = list(Total = ~ sum(.)),
    fmt = ~ fmt_number(., decimals = 0)
  ) %>%
#--- a ready-made look ---#
  opt_stylize(style = 5, color = "gray") %>%
#--- alternate row shading ---#
  opt_row_striping() %>%
#--- tighten the rows ---#
  tab_options(data_row.padding = px(2)) %>%
#--- shrink the type ---#
  tab_options(table.font.size = px(14)) %>%
#--- a title ---#
  tab_header(title = md("**Population of selected Pacific countries**")) %>%
#--- and where it came from ---#
  tab_source_note(source_note = md("Source: `countrypops` in the **gt** package."))
Population of selected Pacific countries
Population
1995 2005
Australasia
Australia 18,004,882 20,176,844
New Zealand 3,673,400 4,133,900
Total 21,678,282 24,310,744
Melanesia
Papua New Guinea 4,616,439 6,498,818
Solomon Islands 375,189 482,486
Vanuatu 170,612 217,632
New Caledonia 193,816 232,250
Total 5,356,056 7,431,186
Polynesia
French Polynesia 231,446 271,060
Samoa 174,902 188,626
Tonga 99,977 105,633
Tuvalu 9,585 9,912
Total 515,910 575,231
Source: countrypops in the gt package.

Output

Transcript

Everything so far produced a table object. This section is about getting it out of R. One function does all of it, and the file extension you give decides the format, which is a nice piece of design because there is nothing else to remember. The list is on screen. Note that PNG and PDF go through a headless browser, so they need the webshot2 package installed, while DOCX needs rmarkdown. The cell here builds a plain table to demonstrate with. HTML and H T M create a self-contained web page, D O C X creates an editable Word document, and R T F creates rich text. T E X and R N W are the LaTeX routes, while P N G and P D F capture the rendered table through webshot two. For the demonstration object, select keeps country name, region, and the two year columns, gt turns them into a table, and the assignment saves that object as table temp. Every gtsave example on the following tabs uses that same object, so only the filename and format-specific options change.

gtsave() writes the table to a file. The extension decides the format:

  • .html, .htm: a self-contained web page
  • .docx: a Word file, as a real editable Word table
  • .rtf: rich text
  • .tex, .rnw: LaTeX
  • .png, .pdf: an image, through the webshot2 package

Let’s create a table for demonstration:

table_temp <-
  tab_data %>%
  dplyr::select(country_name, region, y_1995, y_2005) %>%
  gt()
Transcript

Two lines, and the second is the one that matters for most of you. A gt table saved to docx arrives in Word as a real table, not a picture, so a coauthor can click into a cell and edit it. That is the same argument the flextable deck made, and it is the main practical reason to build tables with code at all. HTML is the format gt was designed around first, so that is the one where everything you have seen on these slides is guaranteed to survive. In each call, table temp is the table object and the quoted filename is the destination. Temp table dot H T M L makes the self-contained web version, while temp table dot D O C X makes the editable Word version. Because gtsave reads the extension, there is no separate format argument to keep synchronized with the filename. Change the path when you want the file saved somewhere other than the current working directory.

HTML

gtsave(table_temp, "temp_table.html")


WORD

gtsave(table_temp, "temp_table.docx")


What arrives in Word is an editable table, not an image.

Transcript

For when you need a picture rather than an editable table, usually for slides. This route needs webshot2, which drives a headless browser to take the screenshot, and it is on CRAN so a plain install packages call is all you need. Look at the two extra arguments in the example. Zoom raises the resolution, which matters if the image is going anywhere near print, and expand adds a margin around the table so it is not cropped tight to the border. Install webshot two once before using either image route. In the P N G call, zoom equal to three renders at three times the base scale for a sharper image, and expand equal to ten adds ten pixels around the captured table. The P D F call supplies no extra options, so it uses the defaults. Both are fixed visual outputs rather than editable tables, which is why they are convenient for placing a finished design on a slide but less useful for a coauthor who needs to change a cell.

First install the webshot2 package.

#--- install ---#
install.packages("webshot2")


png

gtsave(table_temp, "temp_table.png", zoom = 3, expand = 10)


pdf

gtsave(table_temp, "temp_table.pdf")
Transcript

Inside a Quarto document you do not save the table at all. Print it from a chunk and gt works out the right form for whatever you are rendering to, HTML on a website, LaTeX in a PDF. That is the everyday case and it needs no arguments. The as functions below are for when you want the converted object rather than a rendered document, and as raw html is the one that comes up in practice, when you need to paste a table into something that is not Quarto. The other conversions match the same idea. As LaTeX returns LaTeX table code, as R T F returns rich text, and as Word returns the Word X M L representation. These functions do not write a destination file the way gtsave does. They hand the converted representation back to R, which is useful when another function or system needs to receive that representation directly.

In a Quarto document, print the table from a chunk and gt produces the right form for the output format you are rendering to.


When you want the converted object rather than a file:

  • as_raw_html(): the HTML as a character string
  • as_latex(): LaTeX
  • as_rtf(): rich text
  • as_word(): the Word XML

gt or flextable?

Transcript

Both packages make good tables, so this is not a question with one right answer. The differences that actually decide it are in the table on screen. gt formats numbers far better, has row groups and summary rows built in, and needs no second package. flextable was designed around Word and PowerPoint output first, so a table that has to land in a Word document with a specific look tends to be less work there. If you are writing to a website or a Quarto HTML document, gt is the more natural fit. Their location languages also differ. Gt passes cells underscore location functions through locations, while flextable uses i for rows and j for columns. For widths, gt expects you to set explicit values when its content-based sizing is not enough; flextable offers autofit to size from the contents. Those design choices are why the same table can feel much easier in one package even though both can ultimately produce it. Use the final tab to turn these differences into a practical choice.

gt flextable
Designed around HTML first Word and PowerPoint first
Companion package none officer for the fp_*() functions
Saying where cells_*() location functions i = and j =
Number formatting fmt_*(), extensive colformat_*(), fewer options
Row groups built in, groupname_col = approximated with merge_v()
Summary rows built in done by hand before the table
Column widths set explicitly, no autofit autofit()
Transcript

Three plain recommendations rather than a discussion. Writing to a website or a Quarto HTML document, use gt. A table that has to arrive in Word looking a particular way, flextable is usually less work, though gt writes docx too and is worth trying first. And regression tables from modelsummary, which is the next lecture, can be handed to either, so the choice there is whichever you already know.

  • Writing to a website or a Quarto HTML document: gt.
  • A table that must arrive in Word looking a particular way: try gt first, fall back to flextable.
  • Regression tables from modelsummary (next lecture): it produces either, so use whichever you know.