RMarkdown: Color largest percentage in each row of Kable?

Viewed 32

How can RMarkdown correctly color the largest percentage in each row of Kable? The code below incorrectly colors the cell based on the descend order from the 1st digit of the percentages. Thank you in advance! Code:

---
title: "Color Max Percentage"
output:
  html_document: default
  pdf_document: default
---

```{r setup, include = F}
library(tidyverse)
library(knitr)
library(kableExtra)
options(knitr.table.format = "html")

df = data.frame(
  x = c(1, 2, 3, 4, 5),
  a = c("12.7%", "14.0%", "49.2%", "20.4%", "23.2%"),
  b = c("35.6%", "19.0%", "9.1%", "25.5%", "11.2%"),
  c = c("6.9%", "54.1%", "31.3%", "15.4%", "17.5%")
)

df <- df %>%
  # adorn_totals('row') %>% 
  rowwise() %>% 
  mutate(across(a:c,  ~cell_spec(.x, format = "html", 
                                 color = ifelse(.x == max(c_across(a:c)), "red",  "blue"))))
df %>%
  kable(escape = F) %>%
  kable_styling()
```

(Incorrect) output: enter image description here

1 Answers

You are trying to take the maximum of character vectors (i.e. c("12.7%", "35.6%", "6.9%")) and in R,

max(c("12.7%", "35.6%", "6.9%"))
#> [1] "6.9%"

and from ?max and ?comparison,

Character versions are sorted lexicographically, and this depends on the collating sequence of the locale in use: the help for ‘Comparison’ gives details.

Character strings can be compared with different marked encodings (see Encoding): they are translated to UTF-8 before comparison.

sort(c("12.7%", "35.6%", "6.9%"), decreasing = TRUE)
#> [1] "6.9%"  "35.6%" "12.7%"

So, we need to convert them to numbers before comparing using readr::parse_number() and to print the cell values with percent format we can use formattable::percent() function.

---
title: "Color Max Percentage"
output:
  html_document: default
  pdf_document: default
---

```{r setup, include = F}
library(tidyverse)
library(knitr)
library(kableExtra)
options(knitr.table.format = "html")

df = data.frame(
  x = c(1, 2, 3, 4, 5),
  a = c("12.7%", "14.0%", "49.2%", "20.4%", "23.2%"),
  b = c("35.6%", "19.0%", "9.1%", "25.5%", "11.2%"),
  c = c("6.9%", "54.1%", "31.3%", "15.4%", "17.5%")
)

df <- df %>%
  # adorn_totals('row') %>%
  mutate(across(a:c, ~ readr::parse_number(.x) / 100)) %>%
  rowwise() %>%
  mutate(across(
    a:c,
    ~ cell_spec(
      formattable::percent(.x, digits = 1),
      format = "html",
      color = ifelse(.x == max(c_across(a:c)), "red", "blue")
    )
  ))

df %>%
  kable(escape = F) %>%
  kable_styling()

```

maximum cell colored correctly in Kable Table with KableExtra


Related