Tables are an essential part of publishing, well… anything. I therefore want to explore the options available for generating these in knitr. It is important to remember that there are two ways of generating tables in markdown:
As the htmlTable
-package is all about HTML tables we will work
only with that output option. The core idea is that HTML is ubiquitous
and that most word-processors will have to support copy-pasting tables
and by providing simple simple CSS-formatting we are able to maximize
this compatibility. Note CSS is today an extremely complex
topic and it is no surprise that word-processors may have difficulty
importing tables that have lots of advanced syntax, htmlTable tries to
avoid all of that by putting the style close to each element, often at
the cell-level.
I developed the htmlTable
in order to get tables
matching those available in top medical journals. After finding no
HTML-alternative to the Hmisc::latex
function on Stack
Overflow I wrote a basic function allowing column spanners and row
groups. Below is a basic example on these two:
library(htmlTable)
library(magrittr)
setHtmlTableTheme(theme = "Google docs")
<-
output matrix(paste("Content", LETTERS[1:16]),
ncol = 4, byrow = TRUE)
%>%
output htmlTable(header = paste(c("1st", "2nd", "3rd", "4th"), "header"),
rnames = paste(c("1st", "2nd", "3rd", "4th"), "row"),
rgroup = c("Group A", "Group B"),
n.rgroup = c(2, 2),
cgroup = c("Cgroup 1", "Cgroup 2†"),
n.cgroup = c(2, 2),
caption = "Basic table with both column spanners (groups) and row groups",
tfoot = "† A table footer commment")
Cgroup 1 | Cgroup 2† | |||||
---|---|---|---|---|---|---|
1st header | 2nd header | 3rd header | 4th header | |||
Group A | ||||||
1st row | Content A | Content B | Content C | Content D | ||
2nd row | Content E | Content F | Content G | Content H | ||
Group B | ||||||
3rd row | Content I | Content J | Content K | Content L | ||
4th row | Content M | Content N | Content O | Content P | ||
Basic table with both column spanners (groups) and row groups | ||||||
† A table footer commment |
We can modify all our tables by using the
setHtmlTableTemplate()
and we also don’t have to set the
exact span of each group as it can be assumed from the data.
setHtmlTableTheme(pos.caption = "bottom")
%>%
output addHtmlTableStyle(css.rgroup = "font-style: italic") %>%
htmlTable(header = paste(c("1st", "2nd", "3rd", "4th"), "header"),
rnames = paste(c("1st", "2nd", "3rd", "4th"), "row"),
rgroup = c("Group A", "Group B", ""),
n.rgroup = c(1, 2),
cgroup = c("Cgroup 1", "Cgroup 2†"),
n.cgroup = 3,
caption = "A slightly differnt table with a bottom caption",
tfoot = "† A table footer commment")
Cgroup 1 | Cgroup 2† | |||||
---|---|---|---|---|---|---|
1st header | 2nd header | 3rd header | 4th header | |||
Group A | ||||||
1st row | Content A | Content B | Content C | Content D | ||
Group B | ||||||
2nd row | Content E | Content F | Content G | Content H | ||
3rd row | Content I | Content J | Content K | Content L | ||
4th row | Content M | Content N | Content O | Content P | ||
A slightly differnt table with a bottom caption | ||||||
† A table footer commment |
The basic principles are:
%>%
pipe as much as possibleaddHtmlTableStyle()
functionIn order to make a more interesting example we will try to look at how the average age changes between Swedish counties the last 15 years. Goal: visualize migration patterns.
The dataset has been downloaded from Statistics Sweden and is attached to the htmlTable-package. We will start by reshaping our tidy dataset into a more table adapted format.
data(SCB)
# The SCB has three other coulmns and one value column
library(reshape)
$region <- relevel(SCB$region, "Sweden")
SCB<- cast(SCB, year ~ region + sex, value = "values")
SCB
# Set rownames to be year
rownames(SCB) <- SCB$year
$year <- NULL
SCB
# The dataset now has the rows
names(SCB)
## [1] "Sweden_men" "Sweden_women"
## [3] "Norrbotten county_men" "Norrbotten county_women"
## [5] "Stockholm county_men" "Stockholm county_women"
## [7] "Uppsala county_men" "Uppsala county_women"
# and the dimensions
dim(SCB)
## [1] 15 8
The next step is to calculate two new columns:
To convey all these layers of information will create a table with multiple levels of column spanners:
County | ||||||
Men | Women | |||||
Age | Δint. | Δext. | Age | Δint. | Δext. |
<- NULL
mx for (n in names(SCB)) {
<- paste0("Sweden_", strsplit(n, "_")[[1]][2])
tmp <- cbind(mx,
mx cbind(SCB[[n]],
- SCB[[n]][1],
SCB[[n]] - SCB[[tmp]]))
SCB[[n]]
}rownames(mx) <- rownames(SCB)
colnames(mx) <- rep(c("Age",
"Δ<sub>int</sub>",
"Δ<sub>std</sub>"),
times = ncol(SCB))
<- mx[,c(-3, -6)]
mx
# This automated generation of cgroup elements is
# somewhat of an overkill
<-
cgroup unique(sapply(names(SCB),
function(x) strsplit(x, "_")[[1]][1],
USE.NAMES = FALSE))
<-
n.cgroup sapply(cgroup,
function(x) sum(grepl(paste0("^", x), names(SCB))),
USE.NAMES = FALSE)*3
== "Sweden"] <-
n.cgroup[cgroup == "Sweden"] - 2
n.cgroup[cgroup
<-
cgroup rbind(c(cgroup, rep(NA, ncol(SCB) - length(cgroup))),
::capitalize(
Hmiscsapply(names(SCB),
function(x) strsplit(x, "_")[[1]][2],
USE.NAMES = FALSE)))
<-
n.cgroup rbind(c(n.cgroup, rep(NA, ncol(SCB) - length(n.cgroup))),
c(2,2, rep(3, ncol(cgroup) - 2)))
print(cgroup)
## [,1] [,2] [,3] [,4] [,5]
## [1,] "Sweden" "Norrbotten county" "Stockholm county" "Uppsala county" NA
## [2,] "Men" "Women" "Men" "Women" "Men"
## [,6] [,7] [,8]
## [1,] NA NA NA
## [2,] "Women" "Men" "Women"
print(n.cgroup)
## [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8]
## [1,] 4 6 6 6 NA NA NA NA
## [2,] 2 2 3 3 3 3 3 3
Next step is to output the table after rounding to the correct number
of decimals. The txtRound
function helps with this, as it
uses the sprintf
function instead of the round
the resulting strings have the correct number of decimals, i.e. 1.02
will by round become 1 while we want it to retain the last decimal,
i.e. be shown as 1.0.
htmlTable(txtRound(mx, 1),
cgroup = cgroup,
n.cgroup = n.cgroup,
rgroup = c("First period",
"Second period",
"Third period"),
n.rgroup = rep(5, 3),
tfoot = txtMergeLines("Δ<sub>int</sub> correspnds to the change since start",
"Δ<sub>std</sub> corresponds to the change compared to national average"))
Sweden | Norrbotten county | Stockholm county | Uppsala county | |||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Men | Women | Men | Women | Men | Women | Men | Women | |||||||||||||||||||||||||||||
Age | Δint | Age | Δint | Age | Δint | Δstd | Age | Δint | Δstd | Age | Δint | Δstd | Age | Δint | Δstd | Age | Δint | Δstd | Age | Δint | Δstd | |||||||||||||||
First period | ||||||||||||||||||||||||||||||||||||
1999 | 38.9 | 0.0 | 41.5 | 0.0 | 39.7 | 0.0 | 0.8 | 41.9 | 0.0 | 0.4 | 37.3 | 0.0 | -1.6 | 40.1 | 0.0 | -1.4 | 37.2 | 0.0 | -1.7 | 39.3 | 0.0 | -2.2 | ||||||||||||||
2000 | 39.0 | 0.1 | 41.6 | 0.1 | 40.0 | 0.3 | 1.0 | 42.2 | 0.3 | 0.6 | 37.4 | 0.1 | -1.6 | 40.1 | 0.0 | -1.5 | 37.5 | 0.3 | -1.5 | 39.4 | 0.1 | -2.2 | ||||||||||||||
2001 | 39.2 | 0.3 | 41.7 | 0.2 | 40.2 | 0.5 | 1.0 | 42.5 | 0.6 | 0.8 | 37.5 | 0.2 | -1.7 | 40.1 | 0.0 | -1.6 | 37.6 | 0.4 | -1.6 | 39.6 | 0.3 | -2.1 | ||||||||||||||
2002 | 39.3 | 0.4 | 41.8 | 0.3 | 40.5 | 0.8 | 1.2 | 42.8 | 0.9 | 1.0 | 37.6 | 0.3 | -1.7 | 40.2 | 0.1 | -1.6 | 37.8 | 0.6 | -1.5 | 39.7 | 0.4 | -2.1 | ||||||||||||||
2003 | 39.4 | 0.5 | 41.9 | 0.4 | 40.7 | 1.0 | 1.3 | 43.0 | 1.1 | 1.1 | 37.7 | 0.4 | -1.7 | 40.2 | 0.1 | -1.7 | 38.0 | 0.8 | -1.4 | 39.8 | 0.5 | -2.1 | ||||||||||||||
Second period | ||||||||||||||||||||||||||||||||||||
2004 | 39.6 | 0.7 | 42.0 | 0.5 | 40.9 | 1.2 | 1.3 | 43.1 | 1.2 | 1.1 | 37.8 | 0.5 | -1.8 | 40.3 | 0.2 | -1.7 | 38.1 | 0.9 | -1.5 | 40.0 | 0.7 | -2.0 | ||||||||||||||
2005 | 39.7 | 0.8 | 42.0 | 0.5 | 41.1 | 1.4 | 1.4 | 43.4 | 1.5 | 1.4 | 37.9 | 0.6 | -1.8 | 40.3 | 0.2 | -1.7 | 38.3 | 1.1 | -1.4 | 40.1 | 0.8 | -1.9 | ||||||||||||||
2006 | 39.8 | 0.9 | 42.1 | 0.6 | 41.3 | 1.6 | 1.5 | 43.5 | 1.6 | 1.4 | 37.9 | 0.6 | -1.9 | 40.2 | 0.1 | -1.9 | 38.5 | 1.3 | -1.3 | 40.4 | 1.1 | -1.7 | ||||||||||||||
2007 | 39.8 | 0.9 | 42.1 | 0.6 | 41.5 | 1.8 | 1.7 | 43.8 | 1.9 | 1.7 | 37.8 | 0.5 | -2.0 | 40.1 | 0.0 | -2.0 | 38.6 | 1.4 | -1.2 | 40.5 | 1.2 | -1.6 | ||||||||||||||
2008 | 39.9 | 1.0 | 42.1 | 0.6 | 41.7 | 2.0 | 1.8 | 44.0 | 2.1 | 1.9 | 37.8 | 0.5 | -2.1 | 40.1 | 0.0 | -2.0 | 38.7 | 1.5 | -1.2 | 40.5 | 1.2 | -1.6 | ||||||||||||||
Third period | ||||||||||||||||||||||||||||||||||||
2009 | 39.9 | 1.0 | 42.1 | 0.6 | 41.9 | 2.2 | 2.0 | 44.2 | 2.3 | 2.1 | 37.8 | 0.5 | -2.1 | 40.0 | -0.1 | -2.1 | 38.8 | 1.6 | -1.1 | 40.6 | 1.3 | -1.5 | ||||||||||||||
2010 | 40.0 | 1.1 | 42.1 | 0.6 | 42.1 | 2.4 | 2.1 | 44.4 | 2.5 | 2.3 | 37.8 | 0.5 | -2.2 | 40.0 | -0.1 | -2.1 | 38.9 | 1.7 | -1.1 | 40.6 | 1.3 | -1.5 | ||||||||||||||
2011 | 40.1 | 1.2 | 42.2 | 0.7 | 42.3 | 2.6 | 2.2 | 44.5 | 2.6 | 2.3 | 37.9 | 0.6 | -2.2 | 39.9 | -0.2 | -2.3 | 39.0 | 1.8 | -1.1 | 40.7 | 1.4 | -1.5 | ||||||||||||||
2012 | 40.2 | 1.3 | 42.2 | 0.7 | 42.4 | 2.7 | 2.2 | 44.6 | 2.7 | 2.4 | 37.9 | 0.6 | -2.3 | 39.9 | -0.2 | -2.3 | 39.1 | 1.9 | -1.1 | 40.8 | 1.5 | -1.4 | ||||||||||||||
2013 | 40.2 | 1.3 | 42.2 | 0.7 | 42.4 | 2.7 | 2.2 | 44.7 | 2.8 | 2.5 | 38.0 | 0.7 | -2.2 | 39.9 | -0.2 | -2.3 | 39.2 | 2.0 | -1.0 | 40.9 | 1.6 | -1.3 | ||||||||||||||
Δint correspnds to the change since start Δstd corresponds to the change compared to national average |
In order to increase the readability we may want to separate the Sweden columns from the county columns, one way is to use the align option with a |. Note that in 1.0 the function continues with the same alignment until the end, i.e. you no longer need count to have the exact right number of columns in your alignment argument.
%>%
mx txtRound(digits = 1) %>%
addHtmlTableStyle(align = "rrrr|r",
spacer.celltype = "double_cell") %>%
htmlTable(cgroup = cgroup,
n.cgroup = n.cgroup,
rgroup = c("First period",
"Second period",
"Third period"),
n.rgroup = rep(5, 3),
tfoot = txtMergeLines("Δ<sub>int</sub> correspnds to the change since start",
"Δ<sub>std</sub> corresponds to the change compared to national average"))
Sweden | Norrbotten county | Stockholm county | Uppsala county | |||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Men | Women | Men | Women | Men | Women | Men | Women | |||||||||||||||||||||||||||||
Age | Δint | Age | Δint | Age | Δint | Δstd | Age | Δint | Δstd | Age | Δint | Δstd | Age | Δint | Δstd | Age | Δint | Δstd | Age | Δint | Δstd | |||||||||||||||
First period | ||||||||||||||||||||||||||||||||||||
1999 | 38.9 | 0.0 | 41.5 | 0.0 | 39.7 | 0.0 | 0.8 | 41.9 | 0.0 | 0.4 | 37.3 | 0.0 | -1.6 | 40.1 | 0.0 | -1.4 | 37.2 | 0.0 | -1.7 | 39.3 | 0.0 | -2.2 | ||||||||||||||
2000 | 39.0 | 0.1 | 41.6 | 0.1 | 40.0 | 0.3 | 1.0 | 42.2 | 0.3 | 0.6 | 37.4 | 0.1 | -1.6 | 40.1 | 0.0 | -1.5 | 37.5 | 0.3 | -1.5 | 39.4 | 0.1 | -2.2 | ||||||||||||||
2001 | 39.2 | 0.3 | 41.7 | 0.2 | 40.2 | 0.5 | 1.0 | 42.5 | 0.6 | 0.8 | 37.5 | 0.2 | -1.7 | 40.1 | 0.0 | -1.6 | 37.6 | 0.4 | -1.6 | 39.6 | 0.3 | -2.1 | ||||||||||||||
2002 | 39.3 | 0.4 | 41.8 | 0.3 | 40.5 | 0.8 | 1.2 | 42.8 | 0.9 | 1.0 | 37.6 | 0.3 | -1.7 | 40.2 | 0.1 | -1.6 | 37.8 | 0.6 | -1.5 | 39.7 | 0.4 | -2.1 | ||||||||||||||
2003 | 39.4 | 0.5 | 41.9 | 0.4 | 40.7 | 1.0 | 1.3 | 43.0 | 1.1 | 1.1 | 37.7 | 0.4 | -1.7 | 40.2 | 0.1 | -1.7 | 38.0 | 0.8 | -1.4 | 39.8 | 0.5 | -2.1 | ||||||||||||||
Second period | ||||||||||||||||||||||||||||||||||||
2004 | 39.6 | 0.7 | 42.0 | 0.5 | 40.9 | 1.2 | 1.3 | 43.1 | 1.2 | 1.1 | 37.8 | 0.5 | -1.8 | 40.3 | 0.2 | -1.7 | 38.1 | 0.9 | -1.5 | 40.0 | 0.7 | -2.0 | ||||||||||||||
2005 | 39.7 | 0.8 | 42.0 | 0.5 | 41.1 | 1.4 | 1.4 | 43.4 | 1.5 | 1.4 | 37.9 | 0.6 | -1.8 | 40.3 | 0.2 | -1.7 | 38.3 | 1.1 | -1.4 | 40.1 | 0.8 | -1.9 | ||||||||||||||
2006 | 39.8 | 0.9 | 42.1 | 0.6 | 41.3 | 1.6 | 1.5 | 43.5 | 1.6 | 1.4 | 37.9 | 0.6 | -1.9 | 40.2 | 0.1 | -1.9 | 38.5 | 1.3 | -1.3 | 40.4 | 1.1 | -1.7 | ||||||||||||||
2007 | 39.8 | 0.9 | 42.1 | 0.6 | 41.5 | 1.8 | 1.7 | 43.8 | 1.9 | 1.7 | 37.8 | 0.5 | -2.0 | 40.1 | 0.0 | -2.0 | 38.6 | 1.4 | -1.2 | 40.5 | 1.2 | -1.6 | ||||||||||||||
2008 | 39.9 | 1.0 | 42.1 | 0.6 | 41.7 | 2.0 | 1.8 | 44.0 | 2.1 | 1.9 | 37.8 | 0.5 | -2.1 | 40.1 | 0.0 | -2.0 | 38.7 | 1.5 | -1.2 | 40.5 | 1.2 | -1.6 | ||||||||||||||
Third period | ||||||||||||||||||||||||||||||||||||
2009 | 39.9 | 1.0 | 42.1 | 0.6 | 41.9 | 2.2 | 2.0 | 44.2 | 2.3 | 2.1 | 37.8 | 0.5 | -2.1 | 40.0 | -0.1 | -2.1 | 38.8 | 1.6 | -1.1 | 40.6 | 1.3 | -1.5 | ||||||||||||||
2010 | 40.0 | 1.1 | 42.1 | 0.6 | 42.1 | 2.4 | 2.1 | 44.4 | 2.5 | 2.3 | 37.8 | 0.5 | -2.2 | 40.0 | -0.1 | -2.1 | 38.9 | 1.7 | -1.1 | 40.6 | 1.3 | -1.5 | ||||||||||||||
2011 | 40.1 | 1.2 | 42.2 | 0.7 | 42.3 | 2.6 | 2.2 | 44.5 | 2.6 | 2.3 | 37.9 | 0.6 | -2.2 | 39.9 | -0.2 | -2.3 | 39.0 | 1.8 | -1.1 | 40.7 | 1.4 | -1.5 | ||||||||||||||
2012 | 40.2 | 1.3 | 42.2 | 0.7 | 42.4 | 2.7 | 2.2 | 44.6 | 2.7 | 2.4 | 37.9 | 0.6 | -2.3 | 39.9 | -0.2 | -2.3 | 39.1 | 1.9 | -1.1 | 40.8 | 1.5 | -1.4 | ||||||||||||||
2013 | 40.2 | 1.3 | 42.2 | 0.7 | 42.4 | 2.7 | 2.2 | 44.7 | 2.8 | 2.5 | 38.0 | 0.7 | -2.2 | 39.9 | -0.2 | -2.3 | 39.2 | 2.0 | -1.0 | 40.9 | 1.6 | -1.3 | ||||||||||||||
Δint correspnds to the change since start Δstd corresponds to the change compared to national average |
If we still feel that we want more separation it is always possible to add colors.
%>%
mx txtRound(digits = 1) %>%
addHtmlTableStyle(align = "rrrr|r",
align.header = "c",
col.columns = c(rep("#E6E6F0", 4),
rep("none", ncol(mx) - 4))) %>%
htmlTable(cgroup = cgroup,
n.cgroup = n.cgroup,
rgroup = c("First period",
"Second period",
"Third period"),
n.rgroup = rep(5, 3),
tfoot = txtMergeLines("Δ<sub>int</sub> correspnds to the change since start",
"Δ<sub>std</sub> corresponds to the change compared to national average"))
Sweden | Norrbotten county | Stockholm county | Uppsala county | |||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Men | Women | Men | Women | Men | Women | Men | Women | |||||||||||||||||||||||||||||
Age | Δint | Age | Δint | Age | Δint | Δstd | Age | Δint | Δstd | Age | Δint | Δstd | Age | Δint | Δstd | Age | Δint | Δstd | Age | Δint | Δstd | |||||||||||||||
First period | ||||||||||||||||||||||||||||||||||||
1999 | 38.9 | 0.0 | 41.5 | 0.0 | 39.7 | 0.0 | 0.8 | 41.9 | 0.0 | 0.4 | 37.3 | 0.0 | -1.6 | 40.1 | 0.0 | -1.4 | 37.2 | 0.0 | -1.7 | 39.3 | 0.0 | -2.2 | ||||||||||||||
2000 | 39.0 | 0.1 | 41.6 | 0.1 | 40.0 | 0.3 | 1.0 | 42.2 | 0.3 | 0.6 | 37.4 | 0.1 | -1.6 | 40.1 | 0.0 | -1.5 | 37.5 | 0.3 | -1.5 | 39.4 | 0.1 | -2.2 | ||||||||||||||
2001 | 39.2 | 0.3 | 41.7 | 0.2 | 40.2 | 0.5 | 1.0 | 42.5 | 0.6 | 0.8 | 37.5 | 0.2 | -1.7 | 40.1 | 0.0 | -1.6 | 37.6 | 0.4 | -1.6 | 39.6 | 0.3 | -2.1 | ||||||||||||||
2002 | 39.3 | 0.4 | 41.8 | 0.3 | 40.5 | 0.8 | 1.2 | 42.8 | 0.9 | 1.0 | 37.6 | 0.3 | -1.7 | 40.2 | 0.1 | -1.6 | 37.8 | 0.6 | -1.5 | 39.7 | 0.4 | -2.1 | ||||||||||||||
2003 | 39.4 | 0.5 | 41.9 | 0.4 | 40.7 | 1.0 | 1.3 | 43.0 | 1.1 | 1.1 | 37.7 | 0.4 | -1.7 | 40.2 | 0.1 | -1.7 | 38.0 | 0.8 | -1.4 | 39.8 | 0.5 | -2.1 | ||||||||||||||
Second period | ||||||||||||||||||||||||||||||||||||
2004 | 39.6 | 0.7 | 42.0 | 0.5 | 40.9 | 1.2 | 1.3 | 43.1 | 1.2 | 1.1 | 37.8 | 0.5 | -1.8 | 40.3 | 0.2 | -1.7 | 38.1 | 0.9 | -1.5 | 40.0 | 0.7 | -2.0 | ||||||||||||||
2005 | 39.7 | 0.8 | 42.0 | 0.5 | 41.1 | 1.4 | 1.4 | 43.4 | 1.5 | 1.4 | 37.9 | 0.6 | -1.8 | 40.3 | 0.2 | -1.7 | 38.3 | 1.1 | -1.4 | 40.1 | 0.8 | -1.9 | ||||||||||||||
2006 | 39.8 | 0.9 | 42.1 | 0.6 | 41.3 | 1.6 | 1.5 | 43.5 | 1.6 | 1.4 | 37.9 | 0.6 | -1.9 | 40.2 | 0.1 | -1.9 | 38.5 | 1.3 | -1.3 | 40.4 | 1.1 | -1.7 | ||||||||||||||
2007 | 39.8 | 0.9 | 42.1 | 0.6 | 41.5 | 1.8 | 1.7 | 43.8 | 1.9 | 1.7 | 37.8 | 0.5 | -2.0 | 40.1 | 0.0 | -2.0 | 38.6 | 1.4 | -1.2 | 40.5 | 1.2 | -1.6 | ||||||||||||||
2008 | 39.9 | 1.0 | 42.1 | 0.6 | 41.7 | 2.0 | 1.8 | 44.0 | 2.1 | 1.9 | 37.8 | 0.5 | -2.1 | 40.1 | 0.0 | -2.0 | 38.7 | 1.5 | -1.2 | 40.5 | 1.2 | -1.6 | ||||||||||||||
Third period | ||||||||||||||||||||||||||||||||||||
2009 | 39.9 | 1.0 | 42.1 | 0.6 | 41.9 | 2.2 | 2.0 | 44.2 | 2.3 | 2.1 | 37.8 | 0.5 | -2.1 | 40.0 | -0.1 | -2.1 | 38.8 | 1.6 | -1.1 | 40.6 | 1.3 | -1.5 | ||||||||||||||
2010 | 40.0 | 1.1 | 42.1 | 0.6 | 42.1 | 2.4 | 2.1 | 44.4 | 2.5 | 2.3 | 37.8 | 0.5 | -2.2 | 40.0 | -0.1 | -2.1 | 38.9 | 1.7 | -1.1 | 40.6 | 1.3 | -1.5 | ||||||||||||||
2011 | 40.1 | 1.2 | 42.2 | 0.7 | 42.3 | 2.6 | 2.2 | 44.5 | 2.6 | 2.3 | 37.9 | 0.6 | -2.2 | 39.9 | -0.2 | -2.3 | 39.0 | 1.8 | -1.1 | 40.7 | 1.4 | -1.5 | ||||||||||||||
2012 | 40.2 | 1.3 | 42.2 | 0.7 | 42.4 | 2.7 | 2.2 | 44.6 | 2.7 | 2.4 | 37.9 | 0.6 | -2.3 | 39.9 | -0.2 | -2.3 | 39.1 | 1.9 | -1.1 | 40.8 | 1.5 | -1.4 | ||||||||||||||
2013 | 40.2 | 1.3 | 42.2 | 0.7 | 42.4 | 2.7 | 2.2 | 44.7 | 2.8 | 2.5 | 38.0 | 0.7 | -2.2 | 39.9 | -0.2 | -2.3 | 39.2 | 2.0 | -1.0 | 40.9 | 1.6 | -1.3 | ||||||||||||||
Δint correspnds to the change since start Δstd corresponds to the change compared to national average |
If we add a color to the row group and restrict the rgroup spanner we may even have a more visual aid.
%>%
mx txtRound(digits = 1) %>%
addHtmlTableStyle(align = "rrrr|r",
align.header = "c",
col.columns = c(rep("#E6E6F0", 4),
rep("none", ncol(mx) - 4)),
col.rgroup = c("none", "#FFFFCC")) %>%
htmlTable(cgroup = cgroup,
n.cgroup = n.cgroup,
# I use the - the no breaking space as I don't want to have a
# row break in the row group. This adds a little space in the table
# when used together with the cspan.rgroup=1.
rgroup = c("1st period",
"2nd period",
"3rd period"),
n.rgroup = rep(5, 3),
tfoot = txtMergeLines("Δ<sub>int</sub> correspnds to the change since start",
"Δ<sub>std</sub> corresponds to the change compared to national average"),
cspan.rgroup = 1)
Sweden | Norrbotten county | Stockholm county | Uppsala county | |||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Men | Women | Men | Women | Men | Women | Men | Women | |||||||||||||||||||||||||||||
Age | Δint | Age | Δint | Age | Δint | Δstd | Age | Δint | Δstd | Age | Δint | Δstd | Age | Δint | Δstd | Age | Δint | Δstd | Age | Δint | Δstd | |||||||||||||||
1st period | ||||||||||||||||||||||||||||||||||||
1999 | 38.9 | 0.0 | 41.5 | 0.0 | 39.7 | 0.0 | 0.8 | 41.9 | 0.0 | 0.4 | 37.3 | 0.0 | -1.6 | 40.1 | 0.0 | -1.4 | 37.2 | 0.0 | -1.7 | 39.3 | 0.0 | -2.2 | ||||||||||||||
2000 | 39.0 | 0.1 | 41.6 | 0.1 | 40.0 | 0.3 | 1.0 | 42.2 | 0.3 | 0.6 | 37.4 | 0.1 | -1.6 | 40.1 | 0.0 | -1.5 | 37.5 | 0.3 | -1.5 | 39.4 | 0.1 | -2.2 | ||||||||||||||
2001 | 39.2 | 0.3 | 41.7 | 0.2 | 40.2 | 0.5 | 1.0 | 42.5 | 0.6 | 0.8 | 37.5 | 0.2 | -1.7 | 40.1 | 0.0 | -1.6 | 37.6 | 0.4 | -1.6 | 39.6 | 0.3 | -2.1 | ||||||||||||||
2002 | 39.3 | 0.4 | 41.8 | 0.3 | 40.5 | 0.8 | 1.2 | 42.8 | 0.9 | 1.0 | 37.6 | 0.3 | -1.7 | 40.2 | 0.1 | -1.6 | 37.8 | 0.6 | -1.5 | 39.7 | 0.4 | -2.1 | ||||||||||||||
2003 | 39.4 | 0.5 | 41.9 | 0.4 | 40.7 | 1.0 | 1.3 | 43.0 | 1.1 | 1.1 | 37.7 | 0.4 | -1.7 | 40.2 | 0.1 | -1.7 | 38.0 | 0.8 | -1.4 | 39.8 | 0.5 | -2.1 | ||||||||||||||
2nd period | ||||||||||||||||||||||||||||||||||||
2004 | 39.6 | 0.7 | 42.0 | 0.5 | 40.9 | 1.2 | 1.3 | 43.1 | 1.2 | 1.1 | 37.8 | 0.5 | -1.8 | 40.3 | 0.2 | -1.7 | 38.1 | 0.9 | -1.5 | 40.0 | 0.7 | -2.0 | ||||||||||||||
2005 | 39.7 | 0.8 | 42.0 | 0.5 | 41.1 | 1.4 | 1.4 | 43.4 | 1.5 | 1.4 | 37.9 | 0.6 | -1.8 | 40.3 | 0.2 | -1.7 | 38.3 | 1.1 | -1.4 | 40.1 | 0.8 | -1.9 | ||||||||||||||
2006 | 39.8 | 0.9 | 42.1 | 0.6 | 41.3 | 1.6 | 1.5 | 43.5 | 1.6 | 1.4 | 37.9 | 0.6 | -1.9 | 40.2 | 0.1 | -1.9 | 38.5 | 1.3 | -1.3 | 40.4 | 1.1 | -1.7 | ||||||||||||||
2007 | 39.8 | 0.9 | 42.1 | 0.6 | 41.5 | 1.8 | 1.7 | 43.8 | 1.9 | 1.7 | 37.8 | 0.5 | -2.0 | 40.1 | 0.0 | -2.0 | 38.6 | 1.4 | -1.2 | 40.5 | 1.2 | -1.6 | ||||||||||||||
2008 | 39.9 | 1.0 | 42.1 | 0.6 | 41.7 | 2.0 | 1.8 | 44.0 | 2.1 | 1.9 | 37.8 | 0.5 | -2.1 | 40.1 | 0.0 | -2.0 | 38.7 | 1.5 | -1.2 | 40.5 | 1.2 | -1.6 | ||||||||||||||
3rd period | ||||||||||||||||||||||||||||||||||||
2009 | 39.9 | 1.0 | 42.1 | 0.6 | 41.9 | 2.2 | 2.0 | 44.2 | 2.3 | 2.1 | 37.8 | 0.5 | -2.1 | 40.0 | -0.1 | -2.1 | 38.8 | 1.6 | -1.1 | 40.6 | 1.3 | -1.5 | ||||||||||||||
2010 | 40.0 | 1.1 | 42.1 | 0.6 | 42.1 | 2.4 | 2.1 | 44.4 | 2.5 | 2.3 | 37.8 | 0.5 | -2.2 | 40.0 | -0.1 | -2.1 | 38.9 | 1.7 | -1.1 | 40.6 | 1.3 | -1.5 | ||||||||||||||
2011 | 40.1 | 1.2 | 42.2 | 0.7 | 42.3 | 2.6 | 2.2 | 44.5 | 2.6 | 2.3 | 37.9 | 0.6 | -2.2 | 39.9 | -0.2 | -2.3 | 39.0 | 1.8 | -1.1 | 40.7 | 1.4 | -1.5 | ||||||||||||||
2012 | 40.2 | 1.3 | 42.2 | 0.7 | 42.4 | 2.7 | 2.2 | 44.6 | 2.7 | 2.4 | 37.9 | 0.6 | -2.3 | 39.9 | -0.2 | -2.3 | 39.1 | 1.9 | -1.1 | 40.8 | 1.5 | -1.4 | ||||||||||||||
2013 | 40.2 | 1.3 | 42.2 | 0.7 | 42.4 | 2.7 | 2.2 | 44.7 | 2.8 | 2.5 | 38.0 | 0.7 | -2.2 | 39.9 | -0.2 | -2.3 | 39.2 | 2.0 | -1.0 | 40.9 | 1.6 | -1.3 | ||||||||||||||
Δint correspnds to the change since start Δstd corresponds to the change compared to national average |
If you want to further add to the visual hints you can use specific HTML-code and insert it into the cells. Here we will color the Δstd according to color. By default htmlTable does not escape HTML characters.
<- grep("Δ<sub>std</sub>", colnames(mx))
cols_2_clr # We need a copy as the formatting causes the matrix to loos
# its numerical property
<- txtRound(mx, 1)
out_mx
<- min(mx[,cols_2_clr])
min_delta <- max(mx[,cols_2_clr]) - min(mx[,cols_2_clr])
span_delta for (col in cols_2_clr) {
<- mapply(function(val, strength)
out_mx[, col] paste0("<span style='font-weight: 900; color: ",
colorRampPalette(c("#009900", "#000000", "#990033"))(101)[strength],
"'>",
"</span>"),
val, val = out_mx[,col],
strength = round((mx[,col] - min_delta)/span_delta*100 + 1),
USE.NAMES = FALSE)
}
%>%
out_mx addHtmlTableStyle(align = "rrrr|r",
align.header = "cccc|c",
pos.rowlabel = "bottom",
col.rgroup = c("none", "#FFFFCC"),
col.columns = c(rep("#EFEFF0", 4),
rep("none", ncol(mx) - 4))) %>%
htmlTable(caption = "Average age in Sweden counties over a period of
15 years. The Norbotten county is typically known
for having a negative migration pattern compared to
Stockholm, while Uppsala has a proportionally large
population of students.",
rowlabel = "Year",
cgroup = cgroup,
n.cgroup = n.cgroup,
rgroup = c("1st period",
"2nd period",
"3rd period"),
n.rgroup = rep(5, 3),
tfoot = txtMergeLines("Δ<sub>int</sub> corresponds to the change since start",
"Δ<sub>std</sub> corresponds to the change compared to national average"),
cspan.rgroup = 1)
Sweden | Norrbotten county | Stockholm county | Uppsala county | |||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Men | Women | Men | Women | Men | Women | Men | Women | |||||||||||||||||||||||||||||
Year | Age | Δint | Age | Δint | Age | Δint | Δstd | Age | Δint | Δstd | Age | Δint | Δstd | Age | Δint | Δstd | Age | Δint | Δstd | Age | Δint | Δstd | ||||||||||||||
1st period | ||||||||||||||||||||||||||||||||||||
1999 | 38.9 | 0.0 | 41.5 | 0.0 | 39.7 | 0.0 | 0.8 | 41.9 | 0.0 | 0.4 | 37.3 | 0.0 | -1.6 | 40.1 | 0.0 | -1.4 | 37.2 | 0.0 | -1.7 | 39.3 | 0.0 | -2.2 | ||||||||||||||
2000 | 39.0 | 0.1 | 41.6 | 0.1 | 40.0 | 0.3 | 1.0 | 42.2 | 0.3 | 0.6 | 37.4 | 0.1 | -1.6 | 40.1 | 0.0 | -1.5 | 37.5 | 0.3 | -1.5 | 39.4 | 0.1 | -2.2 | ||||||||||||||
2001 | 39.2 | 0.3 | 41.7 | 0.2 | 40.2 | 0.5 | 1.0 | 42.5 | 0.6 | 0.8 | 37.5 | 0.2 | -1.7 | 40.1 | 0.0 | -1.6 | 37.6 | 0.4 | -1.6 | 39.6 | 0.3 | -2.1 | ||||||||||||||
2002 | 39.3 | 0.4 | 41.8 | 0.3 | 40.5 | 0.8 | 1.2 | 42.8 | 0.9 | 1.0 | 37.6 | 0.3 | -1.7 | 40.2 | 0.1 | -1.6 | 37.8 | 0.6 | -1.5 | 39.7 | 0.4 | -2.1 | ||||||||||||||
2003 | 39.4 | 0.5 | 41.9 | 0.4 | 40.7 | 1.0 | 1.3 | 43.0 | 1.1 | 1.1 | 37.7 | 0.4 | -1.7 | 40.2 | 0.1 | -1.7 | 38.0 | 0.8 | -1.4 | 39.8 | 0.5 | -2.1 | ||||||||||||||
2nd period | ||||||||||||||||||||||||||||||||||||
2004 | 39.6 | 0.7 | 42.0 | 0.5 | 40.9 | 1.2 | 1.3 | 43.1 | 1.2 | 1.1 | 37.8 | 0.5 | -1.8 | 40.3 | 0.2 | -1.7 | 38.1 | 0.9 | -1.5 | 40.0 | 0.7 | -2.0 | ||||||||||||||
2005 | 39.7 | 0.8 | 42.0 | 0.5 | 41.1 | 1.4 | 1.4 | 43.4 | 1.5 | 1.4 | 37.9 | 0.6 | -1.8 | 40.3 | 0.2 | -1.7 | 38.3 | 1.1 | -1.4 | 40.1 | 0.8 | -1.9 | ||||||||||||||
2006 | 39.8 | 0.9 | 42.1 | 0.6 | 41.3 | 1.6 | 1.5 | 43.5 | 1.6 | 1.4 | 37.9 | 0.6 | -1.9 | 40.2 | 0.1 | -1.9 | 38.5 | 1.3 | -1.3 | 40.4 | 1.1 | -1.7 | ||||||||||||||
2007 | 39.8 | 0.9 | 42.1 | 0.6 | 41.5 | 1.8 | 1.7 | 43.8 | 1.9 | 1.7 | 37.8 | 0.5 | -2.0 | 40.1 | 0.0 | -2.0 | 38.6 | 1.4 | -1.2 | 40.5 | 1.2 | -1.6 | ||||||||||||||
2008 | 39.9 | 1.0 | 42.1 | 0.6 | 41.7 | 2.0 | 1.8 | 44.0 | 2.1 | 1.9 | 37.8 | 0.5 | -2.1 | 40.1 | 0.0 | -2.0 | 38.7 | 1.5 | -1.2 | 40.5 | 1.2 | -1.6 | ||||||||||||||
3rd period | ||||||||||||||||||||||||||||||||||||
2009 | 39.9 | 1.0 | 42.1 | 0.6 | 41.9 | 2.2 | 2.0 | 44.2 | 2.3 | 2.1 | 37.8 | 0.5 | -2.1 | 40.0 | -0.1 | -2.1 | 38.8 | 1.6 | -1.1 | 40.6 | 1.3 | -1.5 | ||||||||||||||
2010 | 40.0 | 1.1 | 42.1 | 0.6 | 42.1 | 2.4 | 2.1 | 44.4 | 2.5 | 2.3 | 37.8 | 0.5 | -2.2 | 40.0 | -0.1 | -2.1 | 38.9 | 1.7 | -1.1 | 40.6 | 1.3 | -1.5 | ||||||||||||||
2011 | 40.1 | 1.2 | 42.2 | 0.7 | 42.3 | 2.6 | 2.2 | 44.5 | 2.6 | 2.3 | 37.9 | 0.6 | -2.2 | 39.9 | -0.2 | -2.3 | 39.0 | 1.8 | -1.1 | 40.7 | 1.4 | -1.5 | ||||||||||||||
2012 | 40.2 | 1.3 | 42.2 | 0.7 | 42.4 | 2.7 | 2.2 | 44.6 | 2.7 | 2.4 | 37.9 | 0.6 | -2.3 | 39.9 | -0.2 | -2.3 | 39.1 | 1.9 | -1.1 | 40.8 | 1.5 | -1.4 | ||||||||||||||
2013 | 40.2 | 1.3 | 42.2 | 0.7 | 42.4 | 2.7 | 2.2 | 44.7 | 2.8 | 2.5 | 38.0 | 0.7 | -2.2 | 39.9 | -0.2 | -2.3 | 39.2 | 2.0 | -1.0 | 40.9 | 1.6 | -1.3 | ||||||||||||||
Average age in Sweden counties over a period of 15 years. The Norbotten county is typically known for having a negative migration pattern compared to Stockholm, while Uppsala has a proportionally large population of students. | ||||||||||||||||||||||||||||||||||||
Δint corresponds to the change since start Δstd corresponds to the change compared to national average |
Although a graph most likely does the visualization task better, tables are good at conveying detailed information. It is in my mind without doubt easier in the latest version to find the pattern in the data.
Lastly I would like to thank Stephen Few, ThinkUI, ACAPS, and LabWrite for inspiration.