Home > database >  Wrapping column names in KableExtra with str_wrap
Wrapping column names in KableExtra with str_wrap

Time:08-26

I have a table that looks like this:

wide.df <- cbind.data.frame(
  Letter = c("A", "B", "C", "D", "E", "F"),
  `Component 1 - Class Grades`= c(30,25,15,10,10,10),
  `Component 2 - External Grades` = c(10, 10, 10, 15, 25, 30)
)

However, when I output it into kableExtra it obviously comes out looking crappy because of the length of the names.

wide.df %>%   
  knitr::kable(caption = "Example Kable", row.names = F) %>%
  row_spec(0, bold = T, color = "white", background = "darkred")%>%
  add_header_above(c("." = 1, "Count of Grades" = (ncol(wide.df)-1)), background = "darkred", color = "white") %>%
  kable_styling(full_width = FALSE, 
              bootstrap_options = c("striped", "hover", "condensed"),
              fixed_thead = TRUE) 

I'd like these column labels to wrap after the component number, e.g.

Component 1 - Class Grades

Usually I used strwrap in a function for this kind of wrapping for graph titles:

wrapper <- function(x, ...) 
{
  paste(strwrap(x, ...), collapse = "\n")
}

However I can't figure out a way to do this to rename columns in my dataframe to include linebreaks. When I do this it returns nonsense.

I tried to pivot the data to long format and do the renaming, as seen below:

long.df <-
  wide.df %>%
    pivot_longer(-Letter, names_to = "Component", values_to = "Perc") %>%
    mutate(Component = wrapper(Component, 15))

This, however, just gives me incredible long repeats of the component name in that column.

Any help on an easy way to do this? Either by renaming the columns with appropriate breaks in them, or pivoting to long format to rename then pivoting back to wide?

Also, as a bonus - does anyone know how to make my add_header above color in the header over the "Letter" column without including the dummy "." there? When that header value is blank there is no color

CodePudding user response:

Here's a way of solving the problems:

library(dplyr)
library(kableExtra)

wide.df <- cbind.data.frame(
  Letter = c("A", "B", "C", "D", "E", "F"),
  `Component 1 - Class Grades` = c(30, 25, 15, 10, 10, 10),
  `Component 2 - External Grades` = c(10, 10, 10, 15, 25, 30)
)

wrapper <- function(x, ...)
{
  sapply(x, function(y)
    paste(strwrap(y, ...), collapse = "<br>"))
}

wide.df %>%
  rename_with(.fn = wrapper, width = 15) |>
  knitr::kable(caption = "Example Kable",
               row.names = F,
               escape = FALSE) %>%
  row_spec(0,
           bold = T,
           color = "white",
           background = "darkred") %>%
  add_header_above(
    c(
      "<span></span>" = 1,
      "Count of Grades" = (ncol(wide.df) - 1)
    ),
    background = "darkred",
    color = "white",
    escape = FALSE
  ) %>%
  kable_styling(
    full_width = FALSE,
    bootstrap_options = c("striped", "hover", "condensed"),
    fixed_thead = TRUE
  ) 

This works by:

  • Using rename_with to rename columns according to the wrapper function
  • passing the html <br> instead of \n, as the kable parts seemed to ignore the newline
  • (rewriting the wrapper function slightly to handle/return vectors)
  • adding escape = FALSE to knitr::kable to ensure newline is kept in
  • For Bonus question: adding "<span></span>" as a blank column name and escape = FALSE to add_header_above
  • Related