In this post, I will show you some of my best practises for formatting tables in R Markdown. We will cover

  1. How to generally format tables (font, size, color... )

  2. How to create tables with conditional formating (e.g. coloring values < 0 red)

The basics: the R package kableExtra

kableExtra is an awesome package that allows you to format and style your tables. It works similar to ggplot2: You create a base table and then add formating layers with the pipe operator %>%.

```{r myTable}
library(kableExtra)
head(iris) %>%
  kable() %>%
  kable_styling()
```

By default, tables take 100 % of the page width. For tables with few columns, this looks weird. You create less wide tables by setting full_width = FALSE

```{r myTable}
library(kableExtra)
head(iris[1:2]) %>%
  kable() %>%
  kable_styling(full_width = FALSE)
```
Sepal.Length Sepal.Width
5.1 3.5
4.9 3.0
4.7 3.2
4.6 3.1
5.0 3.6
5.4 3.9

You can pass various arguments to kable_styling to influence the font and the position of the table. E.g. font_size = 7 or position = "left". To wrap text around the table use position = "float_right".

Let's increase the font size and position the table on the left.

library(kableExtra)
head(iris[c("Species","Sepal.Length")]) %>%
  kable() %>%
  kable_styling(font_size = 20, position = "left", full_width = FALSE)
Species Sepal.Length
setosa 5.1
setosa 4.9
setosa 4.7
setosa 4.6
setosa 5.0
setosa 5.4

Column and row formatting

You can format specific rows and columns with column_spec() or row_spec(). The first argument is the index of the rows or columns you want to format. Then you can pass formating arguments such as bold = TRUE, color = "black" or background ="grey". So let's make the first column bold, add a right border, color the text black and the background grey.

library(kableExtra)
head(iris[c("Species","Sepal.Length")]) %>%
  kable() %>%
  kable_styling(position = "left", full_width = FALSE) %>%
  column_spec(1, bold = TRUE, border_right = TRUE, color = "black", background = "lightgrey")
Species Sepal.Length
setosa 5.1
setosa 4.9
setosa 4.7
setosa 4.6
setosa 5.0
setosa 5.4

The first and the 6th row have Sepal.Length > 5! We should color the entire row red!

library(kableExtra)
head(iris[c("Species","Sepal.Length")])%>%
  kable() %>%
  kable_styling(position = "left", full_width = FALSE) %>%
  column_spec(1, bold = TRUE, border_right = TRUE, color = "black", background = "lightgrey") %>%
  row_spec(c(1,6), background  = "red")
Species Sepal.Length
setosa 5.1
setosa 4.9
setosa 4.7
setosa 4.6
setosa 5.0
setosa 5.4

At this point you may be wondering: Can I set colors automatically? Yes, of course you can. This is a pretty common task in reports: For example coloring values < 0 in financial reports red. cell_spec is the function you need. You have to apply cell_spec to a data.frame and not knitr_kable object. First you have to create a new column in your data.frame with cell_spec for example by using the mutate function from the dplyr package. Second, apply kable(escape = FALSE). The cell_spec function creates pure html code. That's why you need to pass the additional argument escape = FALSE. Currently, cell_spec supports features including bold, italic, monospace, text color, background color, align, font size and rotation angle.

Here is an example how you could change the color of the text in a cell based on its values:

head(iris[c("Species","Sepal.Length")]) %>%
  mutate(
    Sepal.Length = cell_spec(Sepal.Length, color = ifelse(Sepal.Length > 5, "green","red"))) %>%
  kable(escape = FALSE) %>%
  kable_styling(position = "left", full_width = FALSE) %>%
    column_spec(1, bold = TRUE, border_right = TRUE, color = "black", background = "lightgrey")
Species Sepal.Length
setosa 5.1
setosa 4.9
setosa 4.7
setosa 4.6
setosa 5
setosa 5.4

For more formatting tips such as grouping, popover messages and bootstrapping, I'll refer you to the kableExtra documentation