The htmlTable package is intended for generating tables using HTML formatting. This format is compatible with Markdown when used for HTML-output. The most basic table can easily be created by just passing a matrix
or a data.frame
to the htmlTable
-function:
library(htmlTable)
# A simple output
output <- matrix(1:4,
ncol=2,
dimnames = list(list("Row 1", "Row 2"),
list("Column 1", "Column 2")))
htmlTable(output)
Column 1 | Column 2 | |
---|---|---|
Row 1 | 1 | 3 |
Row 2 | 2 | 4 |
As of version 1.0.2 you no longer need to specify results='asis'
for each knitr
chunk.
While it may be sufficient for basic tables a more advanced layout is often needed in medical publications with elements such as:
- row groups
- column spanners
- table spanners
- caption
- table footer
- zebra coloring (also know as banding):
- rows
- columns
As many journals require that a MS Word-document is submitted it is furthermore also important that the table imports correctly to a word processor, i.e. that the table doesn't only look nice in a web browser but also in the final document. The htmlTable
-function is written for all these purposes.
Note: Due to GitHub CSS-styles the rows get automatically zebra-striped (in a bad way), borders get overridden and I haven't been able to figure out how to change this. See the vignette for a correct example: vignette("general", package = "htmlTable")
For demonstration purposes we will setup a basic matrix:
mx <-
matrix(ncol=6, nrow=8)
rownames(mx) <- paste(c("1st", "2nd",
"3rd",
paste0(4:8, "th")),
"row")
colnames(mx) <- paste(c("1st", "2nd",
"3rd",
paste0(4:6, "th")),
"hdr")
for (nr in 1:nrow(mx)){
for (nc in 1:ncol(mx)){
mx[nr, nc] <-
paste0(nr, ":", nc)
}
}
The purpose of the row groups is to group variables that belong to the same group, e.g. a factored variable with more than two levels often benefit from grouping variables together.
htmlTable(mx,
rgroup = paste("Group", LETTERS[1:3]),
n.rgroup = c(2,4,nrow(mx) - 6))
1st hdr | 2nd hdr | 3rd hdr | 4th hdr | 5th hdr | 6th hdr | |
---|---|---|---|---|---|---|
Group A | ||||||
1st row | 1:1 | 1:2 | 1:3 | 1:4 | 1:5 | 1:6 |
2nd row | 2:1 | 2:2 | 2:3 | 2:4 | 2:5 | 2:6 |
Group B | ||||||
3rd row | 3:1 | 3:2 | 3:3 | 3:4 | 3:5 | 3:6 |
4th row | 4:1 | 4:2 | 4:3 | 4:4 | 4:5 | 4:6 |
5th row | 5:1 | 5:2 | 5:3 | 5:4 | 5:5 | 5:6 |
6th row | 6:1 | 6:2 | 6:3 | 6:4 | 6:5 | 6:6 |
Group C | ||||||
7th row | 7:1 | 7:2 | 7:3 | 7:4 | 7:5 | 7:6 |
8th row | 8:1 | 8:2 | 8:3 | 8:4 | 8:5 | 8:6 |
We can easily mix row groups with regular variables by having an empty row group name ""
:
htmlTable(mx,
rgroup = c(paste("Group", LETTERS[1:2]), ""),
n.rgroup = c(2,4,nrow(mx) - 6))
1st hdr | 2nd hdr | 3rd hdr | 4th hdr | 5th hdr | 6th hdr | |
---|---|---|---|---|---|---|
Group A | ||||||
1st row | 1:1 | 1:2 | 1:3 | 1:4 | 1:5 | 1:6 |
2nd row | 2:1 | 2:2 | 2:3 | 2:4 | 2:5 | 2:6 |
Group B | ||||||
3rd row | 3:1 | 3:2 | 3:3 | 3:4 | 3:5 | 3:6 |
4th row | 4:1 | 4:2 | 4:3 | 4:4 | 4:5 | 4:6 |
5th row | 5:1 | 5:2 | 5:3 | 5:4 | 5:5 | 5:6 |
6th row | 6:1 | 6:2 | 6:3 | 6:4 | 6:5 | 6:6 |
7th row | 7:1 | 7:2 | 7:3 | 7:4 | 7:5 | 7:6 |
8th row | 8:1 | 8:2 | 8:3 | 8:4 | 8:5 | 8:6 |
When mixing row groups with variables without row groups we may want to omit the bold formatting of the row group label:
htmlTable(mx,
css.rgroup = "",
rgroup = c(paste("Group", LETTERS[1:2]), ""),
n.rgroup = c(2,4,nrow(mx) - 6))
1st hdr | 2nd hdr | 3rd hdr | 4th hdr | 5th hdr | 6th hdr | |
---|---|---|---|---|---|---|
Group A | ||||||
1st row | 1:1 | 1:2 | 1:3 | 1:4 | 1:5 | 1:6 |
2nd row | 2:1 | 2:2 | 2:3 | 2:4 | 2:5 | 2:6 |
Group B | ||||||
3rd row | 3:1 | 3:2 | 3:3 | 3:4 | 3:5 | 3:6 |
4th row | 4:1 | 4:2 | 4:3 | 4:4 | 4:5 | 4:6 |
5th row | 5:1 | 5:2 | 5:3 | 5:4 | 5:5 | 5:6 |
6th row | 6:1 | 6:2 | 6:3 | 6:4 | 6:5 | 6:6 |
7th row | 7:1 | 7:2 | 7:3 | 7:4 | 7:5 | 7:6 |
8th row | 8:1 | 8:2 | 8:3 | 8:4 | 8:5 | 8:6 |
A column spanner spans 2 or more columns:
htmlTable(mx,
cgroup = c("Cgroup 1", "Cgroup 2"),
n.cgroup = c(2,4))
Cgroup 1 | Cgroup 2 | ||||||
---|---|---|---|---|---|---|---|
1st hdr | 2nd hdr | 3rd hdr | 4th hdr | 5th hdr | 6th hdr | ||
1st row | 1:1 | 1:2 | 1:3 | 1:4 | 1:5 | 1:6 | |
2nd row | 2:1 | 2:2 | 2:3 | 2:4 | 2:5 | 2:6 | |
3rd row | 3:1 | 3:2 | 3:3 | 3:4 | 3:5 | 3:6 | |
4th row | 4:1 | 4:2 | 4:3 | 4:4 | 4:5 | 4:6 | |
5th row | 5:1 | 5:2 | 5:3 | 5:4 | 5:5 | 5:6 | |
6th row | 6:1 | 6:2 | 6:3 | 6:4 | 6:5 | 6:6 | |
7th row | 7:1 | 7:2 | 7:3 | 7:4 | 7:5 | 7:6 | |
8th row | 8:1 | 8:2 | 8:3 | 8:4 | 8:5 | 8:6 |
It can sometimes be convenient to have column spanners in multiple levels:
htmlTable(mx,
cgroup = rbind(c("", "Column spanners", NA),
c("", "Cgroup 1", "Cgroup 2")),
n.cgroup = rbind(c(1,2,NA),
c(2,2,2)))
Column spanners | ||||||||
---|---|---|---|---|---|---|---|---|
Cgroup 1 | Cgroup 2 | |||||||
1st hdr | 2nd hdr | 3rd hdr | 4th hdr | 5th hdr | 6th hdr | |||
1st row | 1:1 | 1:2 | 1:3 | 1:4 | 1:5 | 1:6 | ||
2nd row | 2:1 | 2:2 | 2:3 | 2:4 | 2:5 | 2:6 | ||
3rd row | 3:1 | 3:2 | 3:3 | 3:4 | 3:5 | 3:6 | ||
4th row | 4:1 | 4:2 | 4:3 | 4:4 | 4:5 | 4:6 | ||
5th row | 5:1 | 5:2 | 5:3 | 5:4 | 5:5 | 5:6 | ||
6th row | 6:1 | 6:2 | 6:3 | 6:4 | 6:5 | 6:6 | ||
7th row | 7:1 | 7:2 | 7:3 | 7:4 | 7:5 | 7:6 | ||
8th row | 8:1 | 8:2 | 8:3 | 8:4 | 8:5 | 8:6 |
Above example allows the column spanner to be a sum of the underlying cgroups (see n.cgroup), this is not required by the function:
htmlTable(mx,
cgroup = rbind(c("", "Column spanners", NA),
c("", "Cgroup 1", "Cgroup 2")),
n.cgroup = rbind(c(1,5,NA),
c(2,1,3)))
Column spanners | |||||||||
---|---|---|---|---|---|---|---|---|---|
Cgroup 1 | Cgroup 2 | ||||||||
1st hdr | 2nd hdr | 3rd hdr | 4th hdr | 5th hdr | 6th hdr | ||||
1st row | 1:1 | 1:2 | 1:3 | 1:4 | 1:5 | 1:6 | |||
2nd row | 2:1 | 2:2 | 2:3 | 2:4 | 2:5 | 2:6 | |||
3rd row | 3:1 | 3:2 | 3:3 | 3:4 | 3:5 | 3:6 | |||
4th row | 4:1 | 4:2 | 4:3 | 4:4 | 4:5 | 4:6 | |||
5th row | 5:1 | 5:2 | 5:3 | 5:4 | 5:5 | 5:6 | |||
6th row | 6:1 | 6:2 | 6:3 | 6:4 | 6:5 | 6:6 | |||
7th row | 7:1 | 7:2 | 7:3 | 7:4 | 7:5 | 7:6 | |||
8th row | 8:1 | 8:2 | 8:3 | 8:4 | 8:5 | 8:6 |
A table spanner is similar to rgroup but has the primary purpose of combining 2 or more tables with the same columns into one:
htmlTable(mx,
tspanner = paste("Spanner", LETTERS[1:3]),
n.tspanner = c(2,4,nrow(mx) - 6))
1st hdr | 2nd hdr | 3rd hdr | 4th hdr | 5th hdr | 6th hdr | |
---|---|---|---|---|---|---|
Spanner A | ||||||
1st row | 1:1 | 1:2 | 1:3 | 1:4 | 1:5 | 1:6 |
2nd row | 2:1 | 2:2 | 2:3 | 2:4 | 2:5 | 2:6 |
Spanner B | ||||||
3rd row | 3:1 | 3:2 | 3:3 | 3:4 | 3:5 | 3:6 |
4th row | 4:1 | 4:2 | 4:3 | 4:4 | 4:5 | 4:6 |
5th row | 5:1 | 5:2 | 5:3 | 5:4 | 5:5 | 5:6 |
6th row | 6:1 | 6:2 | 6:3 | 6:4 | 6:5 | 6:6 |
Spanner C | ||||||
7th row | 7:1 | 7:2 | 7:3 | 7:4 | 7:5 | 7:6 |
8th row | 8:1 | 8:2 | 8:3 | 8:4 | 8:5 | 8:6 |
The table caption is simply the table description and can be either located above or below the table:
htmlTable(mx[1:2,1:2],
caption="A table caption above")
Table 5: A table caption above | ||
1st hdr | 2nd hdr | |
---|---|---|
1st row | 1:1 | 1:2 |
2nd row | 2:1 | 2:2 |
htmlTable(mx[1:2,1:2],
pos.caption = "bottom",
caption="A table caption below")
1st hdr | 2nd hdr | |
---|---|---|
1st row | 1:1 | 1:2 |
2nd row | 2:1 | 2:2 |
Table 6: A table caption below |
A more interesting detail that the function allows for is table numbering, initialized by:
options(table_counter = TRUE)
htmlTable(mx[1:2,1:2],
caption="A table caption with a numbering")
Table 1: A table caption with a numbering | ||
1st hdr | 2nd hdr | |
---|---|---|
1st row | 1:1 | 1:2 |
2nd row | 2:1 | 2:2 |
As we often want to reference the table number in the text there are two associated functions:
tblNoLast()
## [1] 1
tblNoNext()
## [1] 2
The footer usually contains specifics regarding variables and is always located at the foot of the table:
htmlTable(mx[1:2,1:2],
tfoot="A table footer")
1st hdr | 2nd hdr | |
---|---|---|
1st row | 1:1 | 1:2 |
2nd row | 2:1 | 2:2 |
A table footer |
Now if we want to do everything in one table it may look like this:
htmlTable(mx,
align="r",
rgroup = paste("Group", LETTERS[1:3]),
n.rgroup = c(2,4,nrow(mx) - 6),
cgroup = rbind(c("", "Column spanners", NA),
c("", "Cgroup 1", "Cgroup 2†")),
n.cgroup = rbind(c(1,2,NA),
c(2,2,2)),
caption="A table with column spanners, row groups, and zebra striping",
tfoot="† A table footer commment",
cspan.rgroup = 2,
col.columns = c(rep("none", 2),
rep("#F5FBFF", 4)),
col.rgroup = c("none", "#F7F7F7"),
css.cell = "padding-left: .5em; padding-right: .2em;")
Table 2: A table with column spanners, row groups, and zebra striping | ||||||||
Column spanners | ||||||||
---|---|---|---|---|---|---|---|---|
Cgroup 1 | Cgroup 2† | |||||||
1st hdr | 2nd hdr | 3rd hdr | 4th hdr | 5th hdr | 6th hdr | |||
Group A | ||||||||
1st row | 1:1 | 1:2 | 1:3 | 1:4 | 1:5 | 1:6 | ||
2nd row | 2:1 | 2:2 | 2:3 | 2:4 | 2:5 | 2:6 | ||
Group B | ||||||||
3rd row | 3:1 | 3:2 | 3:3 | 3:4 | 3:5 | 3:6 | ||
4th row | 4:1 | 4:2 | 4:3 | 4:4 | 4:5 | 4:6 | ||
5th row | 5:1 | 5:2 | 5:3 | 5:4 | 5:5 | 5:6 | ||
6th row | 6:1 | 6:2 | 6:3 | 6:4 | 6:5 | 6:6 | ||
Group C | ||||||||
7th row | 7:1 | 7:2 | 7:3 | 7:4 | 7:5 | 7:6 | ||
8th row | 8:1 | 8:2 | 8:3 | 8:4 | 8:5 | 8:6 | ||
† A table footer comment |