Chapter 6 Header and footer
flextable
headers, footers and body can be augmented with rows and
the displayed value can be changed.
6.1 Change header labels
Use set_header_labels()
to replace labels of the bottom row of header. When
the flextable is created, their values are the column names of the data.frame.
ft <- flextable(head(airquality))
ft <- set_header_labels(ft, Solar.R = "Solar R (lang)",
Temp = "Temperature (degrees F)", Wind = "Wind (mph)",
Ozone = "Ozone (ppb)" )
ft <- set_table_properties(ft, layout = "autofit", width = .8)
ft
Ozone (ppb) |
Solar R (lang) |
Wind (mph) |
Temperature (degrees F) |
Month |
Day |
---|---|---|---|---|---|
41 |
190 |
7.4 |
67 |
5 |
1 |
36 |
118 |
8.0 |
72 |
5 |
2 |
12 |
149 |
12.6 |
74 |
5 |
3 |
18 |
313 |
11.5 |
62 |
5 |
4 |
<na> |
<na> |
14.3 |
56 |
5 |
5 |
28 |
<na> |
14.9 |
66 |
5 |
6 |
6.2 Separate collapsed colnames into multiple rows
Packages ‘dplyr’ and ‘data.table’ produce aggregated datasets with names representing the arrangements of columns and aggregations.
library(palmerpenguins)
dat <- penguins |>
select(species, island, ends_with("mm")) |>
group_by(species, island) |>
summarise(
across(
where(is.numeric),
.fns = list(
avg = ~ mean(.x, na.rm = TRUE),
sd = ~ sd(.x, na.rm = TRUE)
)
),
.groups = "drop") |>
rename_with(~ tolower(gsub("_mm_", "_", .x, fixed = TRUE)))
dat
# # A tibble: 5 × 8
# species island bill_length_avg bill_length_sd bill_depth_avg bill_depth_sd
# <fct> <fct> <dbl> <dbl> <dbl> <dbl>
# 1 Adelie Biscoe 39.0 2.48 18.4 1.19
# 2 Adelie Dream 38.5 2.47 18.3 1.13
# 3 Adelie Torgers… 39.0 3.03 18.4 1.34
# 4 Chinstrap Dream 48.8 3.34 18.4 1.14
# 5 Gentoo Biscoe 47.5 3.08 15.0 0.981
# # ℹ 2 more variables: flipper_length_avg <dbl>, flipper_length_sd <dbl>
Turning this data.frame to a flextable is not producing an organized version of the data.
ft_pen <- flextable(dat) |>
colformat_double() |>
autofit()
ft_pen
species |
island |
bill_length_avg |
bill_length_sd |
bill_depth_avg |
bill_depth_sd |
flipper_length_avg |
flipper_length_sd |
---|---|---|---|---|---|---|---|
Adelie |
Biscoe |
38.98 |
2.48 |
18.37 |
1.19 |
188.80 |
6.73 |
Adelie |
Dream |
38.50 |
2.47 |
18.25 |
1.13 |
189.73 |
6.59 |
Adelie |
Torgersen |
38.95 |
3.03 |
18.43 |
1.34 |
191.20 |
6.23 |
Chinstrap |
Dream |
48.83 |
3.34 |
18.42 |
1.14 |
195.82 |
7.13 |
Gentoo |
Biscoe |
47.50 |
3.08 |
14.98 |
0.98 |
217.19 |
6.48 |
Using separate_header()
would produce a nicer presentation of the data.
ft_pen <- ft_pen |>
separate_header() |>
align(align = "center", part = "all") |>
autofit()
ft_pen
species |
island |
bill |
flipper |
||||
---|---|---|---|---|---|---|---|
length |
depth |
length |
|||||
avg |
sd |
avg |
sd |
avg |
sd |
||
Adelie |
Biscoe |
38.98 |
2.48 |
18.37 |
1.19 |
188.80 |
6.73 |
Adelie |
Dream |
38.50 |
2.47 |
18.25 |
1.13 |
189.73 |
6.59 |
Adelie |
Torgersen |
38.95 |
3.03 |
18.43 |
1.34 |
191.20 |
6.23 |
Chinstrap |
Dream |
48.83 |
3.34 |
18.42 |
1.14 |
195.82 |
7.13 |
Gentoo |
Biscoe |
47.50 |
3.08 |
14.98 |
0.98 |
217.19 |
6.48 |
6.3 Add rows in header or footer
New header rows can be added at the top or bottom of the header.
Under the hood, the names are in a single row data.frame associated with the header part of the flextable. You can add new rows later, they will be binded to that data.frame.
The functions named below are to be used to add a header line (or a footer line):
- Most needs will be satisfied with functions
add_header_row
andadd_footer_row
. These are row oriented functions to let you add a single row of labels (that can be displayed along one or more columns in the new row). - Functions
add_header
andadd_footer
are columns oriented functions that will let you add several values (one for each new row) for a given column. If labels are stored in a data.frame, use functionsset_header_df
andset_footer_df
. - Functions
add_footer_lines
andadd_header_lines
are sugar functions and should be used to add labels on one single row where all columns are merged together.
We will mainly demonstrate headers but same can be apply with footers.
Now let’s add new row of labels.
6.3.1 Add a row of labels
Use function add_header_row()
: add an header row
where with labels are associated with a number of
columns to merge.
ft <- add_header_row(
x = ft, values = c("air quality measurements", "time"),
colwidths = c(4, 2))
ft <- theme_box(ft)
ft
air quality measurements |
time |
||||
---|---|---|---|---|---|
Ozone (ppb) |
Solar R (lang) |
Wind (mph) |
Temperature (degrees F) |
Month |
Day |
41 |
190 |
7.4 |
67 |
5 |
1 |
36 |
118 |
8.0 |
72 |
5 |
2 |
12 |
149 |
12.6 |
74 |
5 |
3 |
18 |
313 |
11.5 |
62 |
5 |
4 |
<na> |
<na> |
14.3 |
56 |
5 |
5 |
28 |
<na> |
14.9 |
66 |
5 |
6 |
6.3.2 Add lines of text
Use function add_header_lines()
: add labels in new
header rows (all columns are merged).
ft <- add_header_lines(ft,
values = c("this is a first line",
"this is a second line") )
theme_box(ft)
this is a first line | |||||
---|---|---|---|---|---|
this is a second line | |||||
air quality measurements |
time |
||||
Ozone (ppb) |
Solar R (lang) |
Wind (mph) |
Temperature (degrees F) |
Month |
Day |
41 |
190 |
7.4 |
67 |
5 |
1 |
36 |
118 |
8.0 |
72 |
5 |
2 |
12 |
149 |
12.6 |
74 |
5 |
3 |
18 |
313 |
11.5 |
62 |
5 |
4 |
<na> |
<na> |
14.3 |
56 |
5 |
5 |
28 |
<na> |
14.9 |
66 |
5 |
6 |
6.3.3 Define headers with a reference table
Use set_header_df()
with a data.frame as parameter. Columns of
the dataset will be transposed and joined using a key column.
The following illustration is using dataset “people” (see table 15.6).
- The reference table
Variable col_keys
define key values to match with flextable
column keys (defined by argument col_keys
of flextable()
function).
This key column will not be displayed. Other variables will added as rows. Note that variables names are not displayed.
cancers_header
# col_keys line2 line3
# 1 time Follow-up Follow-up
# 2 1_1 I 1
# 3 2_1 I 2
# 4 3_1 I 3
# 5 1_2 II 1
# 6 2_2 II 2
# 7 3_2 II 3
# 8 1_3 III 1
# 9 2_3 III 2
# 10 3_3 III 3
- Use it as header rows
Then use set_header_df()
with parameter key
. key
is the name of the column
used to permform the join operation.
Order of columns matters, first column will be first row, second one will be the second row, etc.
ft <- flextable( cancers, col_keys = cancers_header$col_keys)
ft
time |
1_1 |
2_1 |
3_1 |
1_2 |
2_2 |
3_2 |
1_3 |
2_3 |
3_3 |
---|---|---|---|---|---|---|---|---|---|
1 |
9 |
5 |
1 |
12 |
4 |
1 |
42 |
28 |
19 |
2 |
2 |
2 |
1 |
7 |
3 |
1 |
26 |
19 |
11 |
3 |
9 |
3 |
1 |
5 |
5 |
3 |
12 |
10 |
7 |
4 |
10 |
2 |
1 |
10 |
4 |
1 |
10 |
5 |
6 |
5 |
1 |
2 |
0 |
4 |
2 |
0 |
5 |
0 |
3 |
6 |
3 |
2 |
1 |
3 |
1 |
0 |
4 |
3 |
3 |
7 |
1 |
2 |
0 |
4 |
4 |
2 |
1 |
2 |
3 |
colourer <- scales::col_numeric(
palette = c("transparent", "red"),
domain = c(0, 50))
set_header_df( ft, mapping = cancers_header, key = "col_keys" ) %>%
merge_v(part = "header", j = 1) %>%
merge_h(part = "header", i = 1) %>%
theme_booktabs(bold_header = TRUE) %>%
align(align = "center", part = "all") %>%
bg(
bg = colourer,
j = ~ . -time,
part = "body") %>%
autofit() |>
vline(j = c(1, 4, 7), border = fp_border_default())
Follow-up |
I |
II |
III |
||||||
---|---|---|---|---|---|---|---|---|---|
1 |
2 |
3 |
1 |
2 |
3 |
1 |
2 |
3 |
|
1 |
9 |
5 |
1 |
12 |
4 |
1 |
42 |
28 |
19 |
2 |
2 |
2 |
1 |
7 |
3 |
1 |
26 |
19 |
11 |
3 |
9 |
3 |
1 |
5 |
5 |
3 |
12 |
10 |
7 |
4 |
10 |
2 |
1 |
10 |
4 |
1 |
10 |
5 |
6 |
5 |
1 |
2 |
0 |
4 |
2 |
0 |
5 |
0 |
3 |
6 |
3 |
2 |
1 |
3 |
1 |
0 |
4 |
3 |
3 |
7 |
1 |
2 |
0 |
4 |
4 |
2 |
1 |
2 |
3 |
6.4 footnotes
Adding footnotes is possible by using function compose
but it requires a
two step approach (add the reference symbol and add the corresponding footnote
in the footer part).
To make the process simpler, use function footnote
that will ease the addition
of footnotes.
ft <- flextable(head(iris))
ft <- footnote( ft, i = 1, j = 1:3,
value = as_paragraph(
c("This is footnote one",
"This is footnote two",
"This is footnote three")
),
ref_symbols = c("a", "b", "c"),
part = "header")
ft <- valign(ft, valign = "bottom", part = "header")
autofit(ft)
Sepal.Lengtha |
Sepal.Widthb |
Petal.Lengthc |
Petal.Width |
Species |
---|---|---|---|---|
5.1 |
3.5 |
1.4 |
0.2 |
setosa |
4.9 |
3.0 |
1.4 |
0.2 |
setosa |
4.7 |
3.2 |
1.3 |
0.2 |
setosa |
4.6 |
3.1 |
1.5 |
0.2 |
setosa |
5.0 |
3.6 |
1.4 |
0.2 |
setosa |
5.4 |
3.9 |
1.7 |
0.4 |
setosa |
aThis is footnote one | ||||
bThis is footnote two | ||||
cThis is footnote three |
You can also add footnotes inline using the inline
argument and specify a seperator string with sep
(default “;”)
ft <- flextable(head(iris))
ft <- autofit(ft)
ft <- footnote( ft, i = 1, j = 1:2,
value = as_paragraph(
c("This is footnote one",
"This is footnote two")
),
ref_symbols = c("a", "b"),
part = "header",inline=T)
ft <- footnote( ft, i = 1, j = 3:4,
value = as_paragraph(
c("This is footnote three",
"This is footnote four")
),
ref_symbols = c( "c","d"),
part = "header",inline=T)
ft
Sepal.Lengtha |
Sepal.Widthb |
Petal.Lengthc |
Petal.Widthd |
Species |
---|---|---|---|---|
5.1 |
3.5 |
1.4 |
0.2 |
setosa |
4.9 |
3.0 |
1.4 |
0.2 |
setosa |
4.7 |
3.2 |
1.3 |
0.2 |
setosa |
4.6 |
3.1 |
1.5 |
0.2 |
setosa |
5.0 |
3.6 |
1.4 |
0.2 |
setosa |
5.4 |
3.9 |
1.7 |
0.4 |
setosa |
aThis is footnote one; bThis is footnote two; cThis is footnote three; dThis is footnote four; |