{gt} Tables (2/2)

R gt

In the preceding post, I began exploring basic formatting of {gt} tables. In this post I want to look at the coloring options, cell borders, and custom fonts.

Ani Ruhil true
02-08-2021

Thomas has a great exposition of how to use colors when constructing {gt} tables. I will stick to the basics here so please look at his post for more details. I will also focus on the elements I use or anticipate using – a heatmap table, shading alternative rows or columns to draw a contrast, highlight particular cells to draw attention to specific values or combinations of values, and then of course to just color the header rows or the stub.

Coloring the header rows and/or the stub

Let us start with the easy stuff. Say I want to color the header. First up, the basic table I want to work with, a direct rendition from the {gt} documentation.

library(tidyverse)
library(gt)
library(paletteer)

sza %>%
  filter(latitude == 20) %>%
  select(-latitude) %>%
  filter(!is.na(sza)) %>%
  spread(key = "tst", value = sza) %>%
  gt(rowname_col = "month") %>%
  sub_missing(
    columns = everything(),
    missing_text = ""
  ) %>%
  tab_stubhead(label = html("Month")) %>%
  tab_header(
    title = html("☀ Solar Zenith Angles ☀"),
    subtitle = html("(20°N)")
    ) %>%
  tab_options(
    heading.title.font.size = px(22),
    column_labels.font.size = px(16),
    stub.font.size = "medium",
    table.font.size = "smaller",
    data_row.padding = px(3)
  ) -> mytab01

mytab01
☀ Solar Zenith Angles ☀
(20°N)
Month 0530 0600 0630 0700 0730 0800 0830 0900 0930 1000 1030 1100 1130 1200
jan 84.9 78.7 72.7 66.1 61.5 56.5 52.1 48.3 45.5 43.6 43.0
feb 88.9 82.5 75.8 69.6 63.3 57.7 52.2 47.4 43.1 40.0 37.8 37.2
mar 85.7 78.8 72.0 65.2 58.6 52.3 46.2 40.5 35.5 31.4 28.6 27.7
apr 88.5 81.5 74.4 67.4 60.3 53.4 46.5 39.7 33.2 26.9 21.3 17.2 15.5
may 85.0 78.2 71.2 64.3 57.2 50.2 43.2 36.1 29.1 26.1 15.2 8.8 5.0
jun 89.2 82.7 76.0 69.3 62.5 55.7 48.8 41.9 35.0 28.1 21.1 14.2 7.3 2.0
jul 88.8 82.3 75.7 69.1 62.3 55.5 48.7 41.8 35.0 28.1 21.2 14.3 7.7 3.1
aug 83.8 77.1 70.2 63.3 56.4 49.4 42.4 35.4 28.3 21.3 14.3 7.3 1.9
sep 87.2 80.2 73.2 66.1 59.1 52.1 45.1 38.1 31.3 24.7 18.6 13.7 11.6
oct 84.1 77.1 70.2 63.3 56.5 49.9 43.5 37.5 32.0 27.4 24.3 23.1
nov 87.8 81.3 74.5 68.3 61.8 56.0 50.2 45.3 40.7 37.4 35.1 34.4
dec 84.3 78.0 71.8 66.1 60.5 55.6 50.9 47.2 44.2 42.4 41.8

Now we introduce color by coloring (i) the header, (ii) the stub, and (iii) the data cells.

mytab01 %>%
  tab_options(
    heading.background.color = "#756bb1",
    column_labels.background.color = "#bcbddc",
    column_labels.font.weight = "bold",
    stub.background.color = "#bcbddc",
    stub.font.weight = "bold"
  ) %>%
  tab_style(
    style = list(
      cell_fill(color = "#f2f0f7")
      ),
    locations = cells_body(
    )    
  )
☀ Solar Zenith Angles ☀
(20°N)
Month 0530 0600 0630 0700 0730 0800 0830 0900 0930 1000 1030 1100 1130 1200
jan 84.9 78.7 72.7 66.1 61.5 56.5 52.1 48.3 45.5 43.6 43.0
feb 88.9 82.5 75.8 69.6 63.3 57.7 52.2 47.4 43.1 40.0 37.8 37.2
mar 85.7 78.8 72.0 65.2 58.6 52.3 46.2 40.5 35.5 31.4 28.6 27.7
apr 88.5 81.5 74.4 67.4 60.3 53.4 46.5 39.7 33.2 26.9 21.3 17.2 15.5
may 85.0 78.2 71.2 64.3 57.2 50.2 43.2 36.1 29.1 26.1 15.2 8.8 5.0
jun 89.2 82.7 76.0 69.3 62.5 55.7 48.8 41.9 35.0 28.1 21.1 14.2 7.3 2.0
jul 88.8 82.3 75.7 69.1 62.3 55.5 48.7 41.8 35.0 28.1 21.2 14.3 7.7 3.1
aug 83.8 77.1 70.2 63.3 56.4 49.4 42.4 35.4 28.3 21.3 14.3 7.3 1.9
sep 87.2 80.2 73.2 66.1 59.1 52.1 45.1 38.1 31.3 24.7 18.6 13.7 11.6
oct 84.1 77.1 70.2 63.3 56.5 49.9 43.5 37.5 32.0 27.4 24.3 23.1
nov 87.8 81.3 74.5 68.3 61.8 56.0 50.2 45.3 40.7 37.4 35.1 34.4
dec 84.3 78.0 71.8 66.1 60.5 55.6 50.9 47.2 44.2 42.4 41.8

Now, assume we want a border that demarcates the stub and the column headers from the tables, and to tweak the font-size and, in some case, the font-weights of the contents of the header, column, stub, and cells.

mytab01 %>%
  tab_options(
    heading.background.color = "#756bb1",
    column_labels.background.color = "#bcbddc",
    column_labels.font.weight = "bold",
    stub.background.color = "#bcbddc",
    stub.font.weight = "bold"
  ) %>%
  tab_style(
    style = list(
      cell_fill(color = "#f2f0f7")
      ),
    locations = cells_body(
    )    
  ) %>% 
  tab_style(
    style = list(
      cell_borders(
        sides = "left",
        color = "white",
        weight = px(6)
      )
    ),
    locations = list(
      cells_body(
        columns = vars('0530')
      )
    )
  ) %>%
  tab_style(
    style = list(
      cell_borders(
        sides = "bottom",
        color = "white",
        weight = px(6)
      )
    ),
    locations = list(
      cells_column_labels(
        columns = gt::everything()
      )
    )
  )
☀ Solar Zenith Angles ☀
(20°N)
Month 0530 0600 0630 0700 0730 0800 0830 0900 0930 1000 1030 1100 1130 1200
jan 84.9 78.7 72.7 66.1 61.5 56.5 52.1 48.3 45.5 43.6 43.0
feb 88.9 82.5 75.8 69.6 63.3 57.7 52.2 47.4 43.1 40.0 37.8 37.2
mar 85.7 78.8 72.0 65.2 58.6 52.3 46.2 40.5 35.5 31.4 28.6 27.7
apr 88.5 81.5 74.4 67.4 60.3 53.4 46.5 39.7 33.2 26.9 21.3 17.2 15.5
may 85.0 78.2 71.2 64.3 57.2 50.2 43.2 36.1 29.1 26.1 15.2 8.8 5.0
jun 89.2 82.7 76.0 69.3 62.5 55.7 48.8 41.9 35.0 28.1 21.1 14.2 7.3 2.0
jul 88.8 82.3 75.7 69.1 62.3 55.5 48.7 41.8 35.0 28.1 21.2 14.3 7.7 3.1
aug 83.8 77.1 70.2 63.3 56.4 49.4 42.4 35.4 28.3 21.3 14.3 7.3 1.9
sep 87.2 80.2 73.2 66.1 59.1 52.1 45.1 38.1 31.3 24.7 18.6 13.7 11.6
oct 84.1 77.1 70.2 63.3 56.5 49.9 43.5 37.5 32.0 27.4 24.3 23.1
nov 87.8 81.3 74.5 68.3 61.8 56.0 50.2 45.3 40.7 37.4 35.1 34.4
dec 84.3 78.0 71.8 66.1 60.5 55.6 50.9 47.2 44.2 42.4 41.8

Now we color the cells in ascending order of solar zenith angles, by the hour when the sun zenith angle is measured. We will end up with 12 colors if measurements are available for that hour for all 12 months. As we add these cell colors, we would usually want to remove the background color in the cells for easy viewing of the color range.

mytab01[["_data"]][, c(2:15)] -> dtvals
colnames(dtvals) -> myvars  
suffrager::suf_palette("london", 12, type = "continuous") -> mycolors

mytab01 %>%
  tab_options(
    heading.background.color = "#f4f4f4",
    column_labels.background.color = "#f4f4f4",
    column_labels.font.weight = "bold",
    stub.background.color = "#f4f4f4",
    stub.font.weight = "bold"
  ) %>%
  data_color(
    columns = vars(myvars),
    color = mycolors %>%
      as.character()
      ) %>% 
  tab_style(
    style = list(
      cell_borders(
        sides = "left",
        color = "white",
        weight = px(6)
      )
    ),
    locations = list(
      cells_body(
        columns = vars('0530')
      )
    )
  ) %>%
  tab_style(
    style = list(
      cell_borders(
        sides = "bottom",
        color = "white",
        weight = px(6)
      )
    ),
    locations = list(
      cells_column_labels(
        columns = gt::everything()
      )
    )
  )
☀ Solar Zenith Angles ☀
(20°N)
Month 0530 0600 0630 0700 0730 0800 0830 0900 0930 1000 1030 1100 1130 1200
jan 84.9 78.7 72.7 66.1 61.5 56.5 52.1 48.3 45.5 43.6 43.0
feb 88.9 82.5 75.8 69.6 63.3 57.7 52.2 47.4 43.1 40.0 37.8 37.2
mar 85.7 78.8 72.0 65.2 58.6 52.3 46.2 40.5 35.5 31.4 28.6 27.7
apr 88.5 81.5 74.4 67.4 60.3 53.4 46.5 39.7 33.2 26.9 21.3 17.2 15.5
may 85.0 78.2 71.2 64.3 57.2 50.2 43.2 36.1 29.1 26.1 15.2 8.8 5.0
jun 89.2 82.7 76.0 69.3 62.5 55.7 48.8 41.9 35.0 28.1 21.1 14.2 7.3 2.0
jul 88.8 82.3 75.7 69.1 62.3 55.5 48.7 41.8 35.0 28.1 21.2 14.3 7.7 3.1
aug 83.8 77.1 70.2 63.3 56.4 49.4 42.4 35.4 28.3 21.3 14.3 7.3 1.9
sep 87.2 80.2 73.2 66.1 59.1 52.1 45.1 38.1 31.3 24.7 18.6 13.7 11.6
oct 84.1 77.1 70.2 63.3 56.5 49.9 43.5 37.5 32.0 27.4 24.3 23.1
nov 87.8 81.3 74.5 68.3 61.8 56.0 50.2 45.3 40.7 37.4 35.1 34.4
dec 84.3 78.0 71.8 66.1 60.5 55.6 50.9 47.2 44.2 42.4 41.8

I spent some time trying to figure out how to get the data_color() command to span all data cells, and nirgrahamuk’s answer to a related question gave me the clue.

Notice that the grouping by hour would be okay if we really wanted to see the range by the hour. But what if we had a table where we would like a “proper” heatmap such that the similar cell data values are mapped to the color regardless of the column or row they appear in? By setting the domain = c() to span the minimum and maximum values seen in the data cells.

mytab01[["_data"]][, c(2:15)] -> dtvals
colnames(dtvals) -> myvars
mytab01[["_data"]][, 1] -> dtrows
as.character(dtrows$month) -> myrows
suffrager::suf_palette("london", 12, type = "continuous") -> mycolors

mytab01 %>%
  tab_options(
    heading.background.color = "#f4f4f4",
    column_labels.background.color = "#f4f4f4",
    column_labels.font.weight = "bold",
    stub.background.color = "#f4f4f4",
    stub.font.weight = "bold"
  ) %>%
  data_color(
    columns = vars(myvars),
    colors = scales::col_numeric(
      palette = c(mycolors),
      domain = c(1.9, 89.2)
      )
    ) %>% 
  tab_style(
    style = list(
      cell_borders(
        sides = "left",
        color = "white",
        weight = px(6)
      )
    ),
    locations = list(
      cells_body(
        columns = vars('0530')
      )
    )
  ) %>%
  tab_style(
    style = list(
      cell_borders(
        sides = "bottom",
        color = "white",
        weight = px(6)
      )
    ),
    locations = list(
      cells_column_labels(
        columns = gt::everything()
      )
    )
  )
☀ Solar Zenith Angles ☀
(20°N)
Month 0530 0600 0630 0700 0730 0800 0830 0900 0930 1000 1030 1100 1130 1200
jan 84.9 78.7 72.7 66.1 61.5 56.5 52.1 48.3 45.5 43.6 43.0
feb 88.9 82.5 75.8 69.6 63.3 57.7 52.2 47.4 43.1 40.0 37.8 37.2
mar 85.7 78.8 72.0 65.2 58.6 52.3 46.2 40.5 35.5 31.4 28.6 27.7
apr 88.5 81.5 74.4 67.4 60.3 53.4 46.5 39.7 33.2 26.9 21.3 17.2 15.5
may 85.0 78.2 71.2 64.3 57.2 50.2 43.2 36.1 29.1 26.1 15.2 8.8 5.0
jun 89.2 82.7 76.0 69.3 62.5 55.7 48.8 41.9 35.0 28.1 21.1 14.2 7.3 2.0
jul 88.8 82.3 75.7 69.1 62.3 55.5 48.7 41.8 35.0 28.1 21.2 14.3 7.7 3.1
aug 83.8 77.1 70.2 63.3 56.4 49.4 42.4 35.4 28.3 21.3 14.3 7.3 1.9
sep 87.2 80.2 73.2 66.1 59.1 52.1 45.1 38.1 31.3 24.7 18.6 13.7 11.6
oct 84.1 77.1 70.2 63.3 56.5 49.9 43.5 37.5 32.0 27.4 24.3 23.1
nov 87.8 81.3 74.5 68.3 61.8 56.0 50.2 45.3 40.7 37.4 35.1 34.4
dec 84.3 78.0 71.8 66.1 60.5 55.6 50.9 47.2 44.2 42.4 41.8

Notice I retained the same mycolors palette used earlier but you can always switch palettes out as shown below.

mytab01[["_data"]][, c(2:15)] -> dtvals
colnames(dtvals) -> myvars
mytab01[["_data"]][, 1] -> dtrows
as.character(dtrows$month) -> myrows
suffrager::suf_palette("london", 12, type = "continuous") -> mycolors


mytab01 %>%
  tab_options(
    heading.background.color = "#f4f4f4",
    column_labels.background.color = "#f4f4f4",
    column_labels.font.weight = "bold",
    stub.background.color = "#f4f4f4",
    stub.font.weight = "bold"
  ) %>%
  data_color(
    columns = vars(myvars),
    colors = scales::col_numeric(
      palette = as.character(
        paletteer::paletteer_d(
          "ggsci::red_material",
          n = 9,
          direction = -1
          )
        ),
      domain = c(1.9, 89.2)
      ),
    autocolor_text = TRUE
    ) %>% 
  tab_style(
    style = list(
      cell_borders(
        sides = "left",
        color = "white",
        weight = px(2)
      )
    ),
    locations = list(
      cells_body(
        columns = vars('0530')
      )
    )
  ) %>%
  tab_style(
    style = list(
      cell_borders(
        sides = "bottom",
        color = "white",
        weight = px(2)
      )
    ),
    locations = list(
      cells_column_labels(
        columns = gt::everything()
      )
    )
  )
☀ Solar Zenith Angles ☀
(20°N)
Month 0530 0600 0630 0700 0730 0800 0830 0900 0930 1000 1030 1100 1130 1200
jan 84.9 78.7 72.7 66.1 61.5 56.5 52.1 48.3 45.5 43.6 43.0
feb 88.9 82.5 75.8 69.6 63.3 57.7 52.2 47.4 43.1 40.0 37.8 37.2
mar 85.7 78.8 72.0 65.2 58.6 52.3 46.2 40.5 35.5 31.4 28.6 27.7
apr 88.5 81.5 74.4 67.4 60.3 53.4 46.5 39.7 33.2 26.9 21.3 17.2 15.5
may 85.0 78.2 71.2 64.3 57.2 50.2 43.2 36.1 29.1 26.1 15.2 8.8 5.0
jun 89.2 82.7 76.0 69.3 62.5 55.7 48.8 41.9 35.0 28.1 21.1 14.2 7.3 2.0
jul 88.8 82.3 75.7 69.1 62.3 55.5 48.7 41.8 35.0 28.1 21.2 14.3 7.7 3.1
aug 83.8 77.1 70.2 63.3 56.4 49.4 42.4 35.4 28.3 21.3 14.3 7.3 1.9
sep 87.2 80.2 73.2 66.1 59.1 52.1 45.1 38.1 31.3 24.7 18.6 13.7 11.6
oct 84.1 77.1 70.2 63.3 56.5 49.9 43.5 37.5 32.0 27.4 24.3 23.1
nov 87.8 81.3 74.5 68.3 61.8 56.0 50.2 45.3 40.7 37.4 35.1 34.4
dec 84.3 78.0 71.8 66.1 60.5 55.6 50.9 47.2 44.2 42.4 41.8

The autocolor_text() option is set to TRUE by default and will colorize the text depending upon the fill color, often yielding optimal renderings.

Custom fonts

I have various fonts imported from fonts.google.com that are registered with R. If you are new to registering fonts with R, please see the documentation and vignettes for extrafont here.

mytab01[["_data"]][, c(2:15)] -> dtvals
colnames(dtvals) -> myvars
mytab01[["_data"]][, 1] -> dtrows
as.character(dtrows$month) -> myrows
suffrager::suf_palette("london", 12, type = "continuous") -> mycolors

mytab01 %>%
  tab_options(
    heading.background.color = "#f4f4f4",
    column_labels.background.color = "#f4f4f4",
    stub.background.color = "#f4f4f4"
  ) %>%
 tab_style(
    style = list(
      cell_text(
        font = "Cambay",
        align = "center",
        weight = "bold",
        size = px(18)
      )
    ),
    locations = list(
      cells_title(groups = "title")
    )
  ) %>%
 tab_style(
    style = list(
      cell_text(
        font = "Cambay",
        align = "center",
        weight = "bold",
        size = px(17)
      )
    ),
    locations = list(
      cells_title(groups = "subtitle")
    )
  ) %>%
 tab_style(
    style = list(
      cell_text(
        font = "Siliguri",
        align = "center",
        weight = "bold",
        size = px(16)
      )
    ),
    locations = list(
      cells_stubhead()
    )
  ) %>%
 tab_style(
    style = list(
      cell_text(
        font = "Siliguri",
        align = "center",
        weight = "bold",
        size = px(16)
      )
    ),
    locations = list(
      cells_stub()
    )
  ) %>%
  tab_style(
    style = list(
      cell_text(
        font = "Siliguri",
        weight = "bold",
        size = px(16))
    ),
    locations = list(
      cells_column_labels(gt::everything())
    )
  ) %>%
  tab_style(
    style = list(
      cell_text(
        font = "Siliguri",
        weight = "normal",
        size = px(14))
    ),
    locations = list(
      cells_body()
      )
  ) %>%
  data_color(
    columns = vars(myvars),
    colors = scales::col_numeric(
      palette = as.character(
        paletteer::paletteer_d(
          "ggsci::red_material",
          n = 9,
          direction = -1
          )
        ),
      domain = c(1.9, 89.2)
      ),
    autocolor_text = TRUE
    ) %>% 
  tab_style(
    style = list(
      cell_borders(
        sides = "left",
        color = "white",
        weight = px(2)
      )
    ),
    locations = list(
      cells_body(
        columns = vars('0530')
      )
    )
  ) %>%
  tab_style(
    style = list(
      cell_borders(
        sides = "bottom",
        color = "white",
        weight = px(2)
      )
    ),
    locations = list(
      cells_column_labels(
        columns = gt::everything()
      )
    )
  )
☀ Solar Zenith Angles ☀
(20°N)
Month 0530 0600 0630 0700 0730 0800 0830 0900 0930 1000 1030 1100 1130 1200
jan 84.9 78.7 72.7 66.1 61.5 56.5 52.1 48.3 45.5 43.6 43.0
feb 88.9 82.5 75.8 69.6 63.3 57.7 52.2 47.4 43.1 40.0 37.8 37.2
mar 85.7 78.8 72.0 65.2 58.6 52.3 46.2 40.5 35.5 31.4 28.6 27.7
apr 88.5 81.5 74.4 67.4 60.3 53.4 46.5 39.7 33.2 26.9 21.3 17.2 15.5
may 85.0 78.2 71.2 64.3 57.2 50.2 43.2 36.1 29.1 26.1 15.2 8.8 5.0
jun 89.2 82.7 76.0 69.3 62.5 55.7 48.8 41.9 35.0 28.1 21.1 14.2 7.3 2.0
jul 88.8 82.3 75.7 69.1 62.3 55.5 48.7 41.8 35.0 28.1 21.2 14.3 7.7 3.1
aug 83.8 77.1 70.2 63.3 56.4 49.4 42.4 35.4 28.3 21.3 14.3 7.3 1.9
sep 87.2 80.2 73.2 66.1 59.1 52.1 45.1 38.1 31.3 24.7 18.6 13.7 11.6
oct 84.1 77.1 70.2 63.3 56.5 49.9 43.5 37.5 32.0 27.4 24.3 23.1
nov 87.8 81.3 74.5 68.3 61.8 56.0 50.2 45.3 40.7 37.4 35.1 34.4
dec 84.3 78.0 71.8 66.1 60.5 55.6 50.9 47.2 44.2 42.4 41.8

There is so much more to learn, especially now that I also stumbled across, yes, yet another post by Thomas on how to make better tables, all with {gt}!! Before I work through those rules, exploring {gtsummary} is on deck.

Reuse

Text and figures are licensed under Creative Commons Attribution CC BY-SA 4.0. The figures that have been reused from other sources don't fall under this license and can be recognized by a note in their caption: "Figure from ...".

Citation

For attribution, please cite this work as

Ruhil (2021, Feb. 8). From an Attican Hollow: {gt} Tables (2/2). Retrieved from https://aniruhil.org/posts/2021-02-08-more-with-gt-tables/

BibTeX citation

@misc{ruhil2021{gt},
  author = {Ruhil, Ani},
  title = {From an Attican Hollow: {gt} Tables (2/2)},
  url = {https://aniruhil.org/posts/2021-02-08-more-with-gt-tables/},
  year = {2021}
}