Adding Tables in R Markdown

This chapter is optional. I may refer to it elsewhere as a reference guide for adding tables in R markdown.


In this chapter you will learn how to insert a table in an R markdown (.Rmd) file. You can use this chapter as future reference for when you want to include tables in later chapters.

The User-Friendly Way: kable

Suppose you want to include a correlation matrix of the numeric variables in your data set:

cor(iris[, -5]) # Omit the categorical column 5 (Species)
##              Sepal.Length Sepal.Width Petal.Length Petal.Width
## Sepal.Length    1.0000000  -0.1175698    0.8717538   0.8179411
## Sepal.Width    -0.1175698   1.0000000   -0.4284401  -0.3661259
## Petal.Length    0.8717538  -0.4284401    1.0000000   0.9628654
## Petal.Width     0.8179411  -0.3661259    0.9628654   1.0000000

This is fine if you just want to see the correlation matrix yourself, but in a report you would want to change this into something more presentable.

A fairly straightforward function for including tables is kable. It is part of the knitr package that you use to knit files. Compare the correlation matrix above with the one below:

library("knitr") # Load the functions in knitr, including kable()
kable(cor(iris[, -5]))
Sepal.Length Sepal.Width Petal.Length Petal.Width
Sepal.Length 1.0000000 -0.1175698 0.8717538 0.8179411
Sepal.Width -0.1175698 1.0000000 -0.4284401 -0.3661259
Petal.Length 0.8717538 -0.4284401 1.0000000 0.9628654
Petal.Width 0.8179411 -0.3661259 0.9628654 1.0000000

That’s it! Just wrap kable() around it and knitr will create a decently formatted table in the output. This works identically for knitting to Word, HTML or PDF.

We can improve the table. For starters, it is hard to justify 7 decimals, so let’s change that to 2:

M <- cor(iris[, -5]) # Store the correlation matrix into an object M
kable(round(M, 2))   # Round to 2 decimals
Sepal.Length Sepal.Width Petal.Length Petal.Width
Sepal.Length 1.00 -0.12 0.87 0.82
Sepal.Width -0.12 1.00 -0.43 -0.37
Petal.Length 0.87 -0.43 1.00 0.96
Petal.Width 0.82 -0.37 0.96 1.00

We can also change the periods (.) in the variable names into spaces:

M <- cor(iris[, -5])
rownames(M) <- c("Sepal Length", "Sepal Width", "Petal Length", "Petal Width")
colnames(M) <- c("Sepal Length", "Sepal Width", "Petal Length", "Petal Width")
kable(round(M, 2))
Sepal Length Sepal Width Petal Length Petal Width
Sepal Length 1.00 -0.12 0.87 0.82
Sepal Width -0.12 1.00 -0.43 -0.37
Petal Length 0.87 -0.43 1.00 0.96
Petal Width 0.82 -0.37 0.96 1.00

Or we could do it automatically with the function gsub (useful for larger data sets):

M <- cor(iris[, -5])
rownames(M) <- gsub("[.]", " ", rownames(M)) # Exchange the period with a space
colnames(M) <- gsub("[.]", " ", colnames(M)) # Exchange the period with a space
kable(round(M, 2))

(Output omitted; Identical to the previous table.)

Finally let’s center the numbers and add a caption:

kable(round(M, 2), align = "cccc", caption = "A correlation matrix of the iris data set.")
Table 7.1: A correlation matrix of the iris data set.
Sepal Length Sepal Width Petal Length Petal Width
Sepal Length 1.00 -0.12 0.87 0.82
Sepal Width -0.12 1.00 -0.43 -0.37
Petal Length 0.87 -0.43 1.00 0.96
Petal Width 0.82 -0.37 0.96 1.00

(For those interested, a comprehensive list of formatting options with kable can be found here.)

Exercise 1

Make a table of the first 10 observations in the iris data set using kable. Remember to use library("knitr") to load the kable function. Center all the variables. Knit your R markdown file to see if it renders correctly.

Exercise 2 (*)

For those seeking an extra challenge, create a table that shows the mean (mean) and standard deviation (sd) of each numeric variable, per species.

Advanced: xtable (*)

The package xtable allows for far more control over the formatting. If you want to write professional looking reports in PDF format using R markdown, I recommend familiarizing yourself with xtable. There are no exercises for this paragraph. You may skip this part entirely if you’re fine with just kable.

To install and load xtable, run:

install.packages("xtable")
library("xtable")

Then, it works like this:

Example <- cor(iris[, -5])
Xtable <- xtable(Example, caption = "A correlation matrix of the iris data set.")
align(Xtable) <- "lcccc"
print(Xtable, comment = FALSE, type = "html")
A correlation matrix of the iris data set.
Sepal.Length Sepal.Width Petal.Length Petal.Width
Sepal.Length 1.00 -0.12 0.87 0.82
Sepal.Width -0.12 1.00 -0.43 -0.37
Petal.Length 0.87 -0.43 1.00 0.96
Petal.Width 0.82 -0.37 0.96 1.00

Note: xtable tables only print when you add the chunk option results = "asis".

Here we already see some of the advantages and disadvantages of xtable:

  • It requires more code;
  • It does not automatically label the table;
  • It places the caption below the table by default (a matter of preference);
  • It automatically tries to use a sensible number of digits;
  • It allows separate alignment of the rownames (that’s what the l in lcccc does).

The main power of xtable does not lie in its HTML features, but rather the precise control over tables in \(\LaTeX\). If you want to create professional looking tables in PDF format, have a look at the xtable gallery. Specific examples can be provided per request.

Exercise 3 (*)

Create a PDF file containing the table you made in exercise 2, using the xtable function.