'How to customize background colors based on (characters, NA) contents in multiple columns using gt

Based on the code and data from this link, we can set background colors for the cells of multiple columns based on string contents using gt package:

library(gt)
library(tidyverse)

id <- c(1,2,3,4,5)
res1 <- c("true", "true", "false", "true", "false")
res2 <- c("false", NA, NA, "true", "true")
res3 <- c("true", NA, NA, "true", "true")
df <- data.frame(id, res1, res2, res3)

df %>% 
  gt() %>% 
  data_color(
    columns = c("res1", "res2", 'res3'),
    colors = c("green", "red", 'gray'),
    apply_to = "fill",
    autocolor_text = FALSE)

enter image description here

But as you may noticed, for res3, the color for true is green instead of red as in other two columns. If I hope to set red for true, green for false and gray for NA, for these 3 columns, if in case, they have other values such as yes, no, etc., just keep as original.

How could we solve this problem? Many thanks at advance.

Update1: an alternative solution with tab_style(), but not concise:

df %>% 
  gt() %>% 
  tab_style(
    style = list(
      cell_fill(color = 'red')
    ),
    locations = cells_body(
      columns = res1,
      rows = res1 == "true"
    )
  ) %>% 
  tab_style(
    style = list(
      cell_fill(color = 'red')
    ),
    locations = cells_body(
      columns = res2,
      rows = res2 == "true"
    )
  ) %>% 
  tab_style(
    style = list(
      cell_fill(color = 'red')
    ),
    locations = cells_body(
      columns = res3,
      rows = res3 == "true"
    )
  ) %>% 
  tab_style(
    style = list(
      cell_fill(color = 'green')
    ),
    locations = cells_body(
      columns = res1,
      rows = res1 == "false"
    )
  ) %>% 
  tab_style(
    style = list(
      cell_fill(color = 'green')
    ),
    locations = cells_body(
      columns = res2,
      rows = res2 == "false"
    )
  ) %>% 
  tab_style(
    style = list(
      cell_fill(color = 'green')
    ),
    locations = cells_body(
      columns = res3,
      rows = res3 == "false"
    )
  ) %>% 
  tab_style(
    style = list(
      cell_fill(color = 'gray')
    ),
    locations = cells_body(
      columns = res1,
      rows = res1 == NA
    )
  ) %>% 
  tab_style(
    style = list(
      cell_fill(color = 'gray')
    ),
    locations = cells_body(
      columns = res2,
      rows = res2 == NA
    )
  ) %>% 
  tab_style(
    style = list(
      cell_fill(color = 'gray')
    ),
    locations = cells_body(
      columns = res3,
      rows = res3 == NA
    )
  )

enter image description here

Update2: How to correctly set gray color for NA cells?

cols <- c('res1', 'res2', 'res3')
df %>% 
  # mutate_each_(funs(factor(.)), cols)
  mutate_at(cols, factor) %>% 
  gt() %>% 
  data_color(
    columns = cols,
    colors = scales::col_factor(
      palette = c('green', 'red', 'gray'),
      domain = c('false', 'true', NA)
    ),
    apply_to = "fill",
    autocolor_text = FALSE
  )

enter image description here

Update3: I set palette = c("green", "red", 'yellow'), domain = c("false", "true", '-'), why it's not shown green for false, red for true, and yellow for -?

id <- c(1, 2, 3, 4, 5)
res1 <- c("true", "true", "false", "true", "false")
res2 <- c("false", NA, NA, "true", "-")
res3 <- c("true", NA, NA, "true", "true")
df <- data.frame(id, res1, res2, res3)

df %>% 
  mutate_at(cols, factor) %>% 
  gt() %>% 
  data_color(
    columns = cols,
    colors = scales::col_factor(
      palette = c("green", "red", 'yellow'),
      domain = c("false", "true", '-'),
      na.color = 'gray'
    ),
    apply_to = "fill",
    autocolor_text = FALSE
  )

enter image description here

References:

Set background color if one cell's (of multiple columns) content is specific string using gt package

rgt


Solution 1:[1]

It's not a good idea to store your logical values as character strings. If you use TRUE and FALSE values instead, gt() works as designed to give you the table coloring you want.

id <- c(1,2,3,4,5)
res1 <- c(TRUE, TRUE, FALSE, TRUE, FALSE)
res2 <- c(FALSE, NA, NA, TRUE, TRUE)
res3 <- c(TRUE, NA, NA, TRUE, TRUE)
df2 <- data.frame(id, res1, res2, res3)

df2 %>% 
  gt() %>% 
  data_color(
    columns = c(res1, res2, res3),
    colors = scales::col_factor(
      palette = c("green", "red"),
      domain = c(FALSE, TRUE)
    ),
    apply_to = "fill",
    autocolor_text = FALSE
  )

If there's some reason you have to have the logicals as character strings you'll need to convert them to a factor and adjust the domain argument in data_color().

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 rdelrossi