90 Tables: kable, kableextra, and gt
Written by Yena Joo and last updated on 7 October 2021.
90.1 Introduction
In the research papers, tables are used all the time. However, the dataframe itself looks unorganized and latex-y when the R file is converted into PDF or HTML. To make nice and beautiful tables, we are going to learn how to use kable
and kableextra
.
In this lesson, you will learn how to:
- Create Tables In LaTeX, HTML, Markdown
- build common complex tables and manipulate table styles using
kableExtra
Prerequisite skills include:
- manipulate dataset
- You don’t need much prerequisite for this chapter :)
Highlights:
- How to create tables for HTML and PDF.
-
kable
,kableExtra
,gt
90.2 Kable()
kable()
function in knitr
package is a table generator.
90.2.1 Arguments of kable()
kable(x, format, digits = getOption("digits"), row.names = NA,
col.names = NA, align, caption = NULL, label = NULL,
format.args = list(), escape = TRUE, ...)
Here are some important arguments of kable()
:
-
x
: put the data frame of your choice.
-
format
: possible values are “latex,” “html,” “simple,” “pipe,” “rst.”
-
digit
: maximum number of digits for numeric columns.
-
row.names
&col.names
: column names and row names.
If you want the full descriptions of each argument, click here or type help("kable")
into your console.
First, let’s use a built-in dataset mtcars
as an example. We simply put the dataset name as the argument x of the function kbl
or kable
. Then, it creates the most basic table output as follows. Note that for R Markdown documents, the function uses the format “pipe” by default.
mpg | cyl | disp | hp | drat | wt | qsec | vs | am | gear | carb | |
---|---|---|---|---|---|---|---|---|---|---|---|
Mazda RX4 | 21.0 | 6 | 160 | 110 | 3.90 | 2.620 | 16.46 | 0 | 1 | 4 | 4 |
Mazda RX4 Wag | 21.0 | 6 | 160 | 110 | 3.90 | 2.875 | 17.02 | 0 | 1 | 4 | 4 |
Datsun 710 | 22.8 | 4 | 108 | 93 | 3.85 | 2.320 | 18.61 | 1 | 1 | 4 | 1 |
Hornet 4 Drive | 21.4 | 6 | 258 | 110 | 3.08 | 3.215 | 19.44 | 1 | 0 | 3 | 1 |
Hornet Sportabout | 18.7 | 8 | 360 | 175 | 3.15 | 3.440 | 17.02 | 0 | 0 | 3 | 2 |
Valiant | 18.1 | 6 | 225 | 105 | 2.76 | 3.460 | 20.22 | 1 | 0 | 3 | 1 |
90.2.2 Formatting of kable
There are several arguments you can customize the tables.
For example, you can set the format of the table using format = "html"
.
You can also add a title to the table using caption = ""
argument.
digits =
allows you to round and format the numbers in the table.
Let’s try to create an HTML table with a caption.
mpg | cyl | disp | hp | drat | wt | qsec | vs | am | gear | carb | |
---|---|---|---|---|---|---|---|---|---|---|---|
Mazda RX4 | 21.0 | 6 | 160 | 110 | 3.90 | 2.620 | 16.46 | 0 | 1 | 4 | 4 |
Mazda RX4 Wag | 21.0 | 6 | 160 | 110 | 3.90 | 2.875 | 17.02 | 0 | 1 | 4 | 4 |
Datsun 710 | 22.8 | 4 | 108 | 93 | 3.85 | 2.320 | 18.61 | 1 | 1 | 4 | 1 |
However, the basic HTML output of kable
does not look so pretty, since it is just a plain HTML table without any styling.
We can also change the column names or row names using col.names
or row.names
. Let’s customize the table above into the format “simple,” as well as with changed column names.
kable(x = dt, format = "simple", caption = "Title of the table", col.names = c("1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11"))
1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | |
---|---|---|---|---|---|---|---|---|---|---|---|
Mazda RX4 | 21.0 | 6 | 160 | 110 | 3.90 | 2.620 | 16.46 | 0 | 1 | 4 | 4 |
Mazda RX4 Wag | 21.0 | 6 | 160 | 110 | 3.90 | 2.875 | 17.02 | 0 | 1 | 4 | 4 |
Datsun 710 | 22.8 | 4 | 108 | 93 | 3.85 | 2.320 | 18.61 | 1 | 1 | 4 | 1 |
Note that only the pipe
and simple
formats work in any output document format. Formats such as latex
or html
only work on the specific format of the document output.
90.3 kableExtra
The kableExtra
package allows you to add a lot more features and options to your simple table you made using the function kable()
. The package features the pipe operator, %>%
, so you can pipe the table to add more features.
90.3.1 kable_styling()
To make the plain HTML table we just created look prettier, you can always apply themes using kable_styling()
from the package kableExtra
to make the tables look more fancy and neat.
The function has the following arguments:
kable_styling(
kable_input,
bootstrap_options = "basic",
latex_options = "basic",
full_width = NULL,
position = "center",
font_size = NULL,....
Details of the arguments can be found here.
First, let’s just try using the function without any argument. kable_styling()
will automatically apply Twitter bootstrap theme to the table.
kable(x = head(mtcars[1:3,])) %>%
kable_styling()
mpg | cyl | disp | hp | drat | wt | qsec | vs | am | gear | carb | |
---|---|---|---|---|---|---|---|---|---|---|---|
Mazda RX4 | 21.0 | 6 | 160 | 110 | 3.90 | 2.620 | 16.46 | 0 | 1 | 4 | 4 |
Mazda RX4 Wag | 21.0 | 6 | 160 | 110 | 3.90 | 2.875 | 17.02 | 0 | 1 | 4 | 4 |
Datsun 710 | 22.8 | 4 | 108 | 93 | 3.85 | 2.320 | 18.61 | 1 | 1 | 4 | 1 |
As you can see, it creates a nice and simple table.
Using kable_styling
, you can also adjust the size and position of the table, font sizes, etc. as the following:
kable(x = dt, format = "html") %>%
kable_styling(bootstrap_options = "striped", full_width = F, position = "left", font_size = 10)
mpg | cyl | disp | hp | drat | wt | qsec | vs | am | gear | carb | |
---|---|---|---|---|---|---|---|---|---|---|---|
Mazda RX4 | 21.0 | 6 | 160 | 110 | 3.90 | 2.620 | 16.46 | 0 | 1 | 4 | 4 |
Mazda RX4 Wag | 21.0 | 6 | 160 | 110 | 3.90 | 2.875 | 17.02 | 0 | 1 | 4 | 4 |
Datsun 710 | 22.8 | 4 | 108 | 93 | 3.85 | 2.320 | 18.61 | 1 | 1 | 4 | 1 |
You can try various options using the function kable_styling
. Here are some more nice and detailed examples for a reference.
90.3.2 How to put multiple tables side by side
You can pass a list of dataframes to kable()
which generates side-by-side tables.
Here, I will split mtcars
dataset into two tables, and put them side by side using kable(list(datasets))
.
data1 <- head(mtcars[1:3, 1:3])
data2 <- head(mtcars[, 4:7])
knitr::kable(
x = list(data1, data2), format = "html",
caption = 'Tables side by side.',
booktabs = TRUE, valign = 't'
) %>% kable_styling(bootstrap_options = "striped")
|
|
This feature only works for html and pdf output.
Another way to put tables side by side is to use kables()
.
kables(list(
kable(data1, caption = "first table") %>% kable_styling(bootstrap_options = "striped"),
kable(data2, caption= "second table") %>% kable_styling(bootstrap_options = "striped")))
|
|
By using kables
function, you can pass the list of kable()
objects to it. You can also set different titles for each table.
90.4 GT Table
The gt package is used to produce nice-looking display tables. Here, we distinguish between data tables(tibbles, dataframes, etc) and the display tables easily found in articles, and web pages.
In order to produce the gt table, gt package is needed.
Given that data
is a tibble which we have a suitable input for gt.
We use gt()
function. If we pass the tibble to the gt() function, we’ll get a gt Table as an output.
mpg | cyl | disp | hp | drat | wt | qsec | vs | am | gear | carb |
---|---|---|---|---|---|---|---|---|---|---|
21.0 | 6 | 160 | 110 | 3.90 | 2.620 | 16.46 | 0 | 1 | 4 | 4 |
21.0 | 6 | 160 | 110 | 3.90 | 2.875 | 17.02 | 0 | 1 | 4 | 4 |
22.8 | 4 | 108 | 93 | 3.85 | 2.320 | 18.61 | 1 | 1 | 4 | 1 |
21.4 | 6 | 258 | 110 | 3.08 | 3.215 | 19.44 | 1 | 0 | 3 | 1 |
18.7 | 8 | 360 | 175 | 3.15 | 3.440 | 17.02 | 0 | 0 | 3 | 2 |
18.1 | 6 | 225 | 105 | 2.76 | 3.460 | 20.22 | 1 | 0 | 3 | 1 |
90.4.1 Add parts to the gt Table
You can add titles and labels for various levels on the gt Tables. The picture below shows the parts you can put the title/labels at.
To add a title, you used the tab_header
function to add labels or titles.
mt_table <-
mt_table %>%
tab_header(
title = "This is a title",
subtitle = "This is a subtitle"
)
mt_table
This is a title | ||||||||||
---|---|---|---|---|---|---|---|---|---|---|
This is a subtitle | ||||||||||
mpg | cyl | disp | hp | drat | wt | qsec | vs | am | gear | carb |
21.0 | 6 | 160 | 110 | 3.90 | 2.620 | 16.46 | 0 | 1 | 4 | 4 |
21.0 | 6 | 160 | 110 | 3.90 | 2.875 | 17.02 | 0 | 1 | 4 | 4 |
22.8 | 4 | 108 | 93 | 3.85 | 2.320 | 18.61 | 1 | 1 | 4 | 1 |
21.4 | 6 | 258 | 110 | 3.08 | 3.215 | 19.44 | 1 | 0 | 3 | 1 |
18.7 | 8 | 360 | 175 | 3.15 | 3.440 | 17.02 | 0 | 0 | 3 | 2 |
18.1 | 6 | 225 | 105 | 2.76 | 3.460 | 20.22 | 1 | 0 | 3 | 1 |
90.5 Exercises
90.5.1 Question 1
Create a table that has a title “This is a table,” bootstrap options being stripe
, and having full width, with a right
position, using the dataset data
.
data <- head(mtcars)
data <- head(mtcars)
kable(x = data, caption = "This is a table", position = "right", full_width = T)
mpg | cyl | disp | hp | drat | wt | qsec | vs | am | gear | carb | |
---|---|---|---|---|---|---|---|---|---|---|---|
Mazda RX4 | 21.0 | 6 | 160 | 110 | 3.90 | 2.620 | 16.46 | 0 | 1 | 4 | 4 |
Mazda RX4 Wag | 21.0 | 6 | 160 | 110 | 3.90 | 2.875 | 17.02 | 0 | 1 | 4 | 4 |
Datsun 710 | 22.8 | 4 | 108 | 93 | 3.85 | 2.320 | 18.61 | 1 | 1 | 4 | 1 |
Hornet 4 Drive | 21.4 | 6 | 258 | 110 | 3.08 | 3.215 | 19.44 | 1 | 0 | 3 | 1 |
Hornet Sportabout | 18.7 | 8 | 360 | 175 | 3.15 | 3.440 | 17.02 | 0 | 0 | 3 | 2 |
Valiant | 18.1 | 6 | 225 | 105 | 2.76 | 3.460 | 20.22 | 1 | 0 | 3 | 1 |
90.5.2 Question 2
Now, use kable_styling()
to create the same table, but with striped
bootstrap option.
data <- head(mtcars)
data <- head(mtcars)
kable(x = data, caption = "This is a table", position = "right", full_width = T) %>% kable_styling(bootstrap_options = 'striped')
mpg | cyl | disp | hp | drat | wt | qsec | vs | am | gear | carb | |
---|---|---|---|---|---|---|---|---|---|---|---|
Mazda RX4 | 21.0 | 6 | 160 | 110 | 3.90 | 2.620 | 16.46 | 0 | 1 | 4 | 4 |
Mazda RX4 Wag | 21.0 | 6 | 160 | 110 | 3.90 | 2.875 | 17.02 | 0 | 1 | 4 | 4 |
Datsun 710 | 22.8 | 4 | 108 | 93 | 3.85 | 2.320 | 18.61 | 1 | 1 | 4 | 1 |
Hornet 4 Drive | 21.4 | 6 | 258 | 110 | 3.08 | 3.215 | 19.44 | 1 | 0 | 3 | 1 |
Hornet Sportabout | 18.7 | 8 | 360 | 175 | 3.15 | 3.440 | 17.02 | 0 | 0 | 3 | 2 |
Valiant | 18.1 | 6 | 225 | 105 | 2.76 | 3.460 | 20.22 | 1 | 0 | 3 | 1 |
90.5.3 Question 3
Put the following data frames side by side, with the title “Tables are side by side.” Drop the decimal places using the argument digits
.
|
|
90.6 Common Mistakes & Errors
You might get the following error message sometimes:
Error in dimnames(x) <- dn : length of 'dimnames' [2] not equal to array extent
This error message will pop up if you are trying to change the column names with different length of the vector than the number of columns. Make sure the length of the vector in your col.names
argument matches the number of the columns in the dataset.
Also, make sure to choose the right format of kable that matches the format of the document. If you choose to put format = "pdf"
in a HTML document output, you will get the following error:
could not find function "kable_pdf"
So be careful not to make these mistakes.