library(tinytable)
options(tinytable_tt_digits = 3)
options(tinytable_theme_placement_latex_float = "H")
<- mtcars[1:4, 1:5] x
Groups and labels
The group_tt()
function can label groups of rows (i
) or columns (j
).
Rows
The i
argument accepts a named list of integers. The numbers identify the positions where row group labels are to be inserted. The names includes the text that should be inserted:
<- mtcars[1:9, 1:8]
dat
tt(dat) |>
group_tt(i = list(
"I like (fake) hamburgers" = 3,
"She prefers halloumi" = 4,
"They love tofu" = 7))
mpg | cyl | disp | hp | drat | wt | qsec | vs |
---|---|---|---|---|---|---|---|
21 | 6 | 160 | 110 | 3.9 | 2.62 | 16.5 | 0 |
21 | 6 | 160 | 110 | 3.9 | 2.88 | 17 | 0 |
22.8 | 4 | 108 | 93 | 3.85 | 2.32 | 18.6 | 1 |
21.4 | 6 | 258 | 110 | 3.08 | 3.21 | 19.4 | 1 |
18.7 | 8 | 360 | 175 | 3.15 | 3.44 | 17 | 0 |
18.1 | 6 | 225 | 105 | 2.76 | 3.46 | 20.2 | 1 |
14.3 | 8 | 360 | 245 | 3.21 | 3.57 | 15.8 | 0 |
24.4 | 4 | 147 | 62 | 3.69 | 3.19 | 20 | 1 |
22.8 | 4 | 141 | 95 | 3.92 | 3.15 | 22.9 | 1 |
The numbers in the i
list indicate that a label must be inserted at position # in the original table (without row groups). For example,
tt(head(iris)) |>
group_tt(i = list("After 1" = 2, "After 2" = 3, "After 3" = 4, "After 5" = 6))
Sepal.Length | Sepal.Width | Petal.Length | Petal.Width | Species |
---|---|---|---|---|
5.1 | 3.5 | 1.4 | 0.2 | setosa |
4.9 | 3 | 1.4 | 0.2 | setosa |
4.7 | 3.2 | 1.3 | 0.2 | setosa |
4.6 | 3.1 | 1.5 | 0.2 | setosa |
5 | 3.6 | 1.4 | 0.2 | setosa |
5.4 | 3.9 | 1.7 | 0.4 | setosa |
tt(head(iris)) |>
group_tt(i = list("After 1a" = 2, "After 1b" = 2, "After 5" = 6))
Sepal.Length | Sepal.Width | Petal.Length | Petal.Width | Species |
---|---|---|---|---|
5.1 | 3.5 | 1.4 | 0.2 | setosa |
4.9 | 3 | 1.4 | 0.2 | setosa |
4.7 | 3.2 | 1.3 | 0.2 | setosa |
4.6 | 3.1 | 1.5 | 0.2 | setosa |
5 | 3.6 | 1.4 | 0.2 | setosa |
5.4 | 3.9 | 1.7 | 0.4 | setosa |
tt(head(iris)) |>
group_tt(i = list("After 0" = 1))
Sepal.Length | Sepal.Width | Petal.Length | Petal.Width | Species |
---|---|---|---|---|
5.1 | 3.5 | 1.4 | 0.2 | setosa |
4.9 | 3 | 1.4 | 0.2 | setosa |
4.7 | 3.2 | 1.3 | 0.2 | setosa |
4.6 | 3.1 | 1.5 | 0.2 | setosa |
5 | 3.6 | 1.4 | 0.2 | setosa |
5.4 | 3.9 | 1.7 | 0.4 | setosa |
We can style group rows in the same way as regular rows (caveat: not in Word or Markdown):
tt(dat) |>
group_tt(
i = list(
"I like (fake) hamburgers" = 3,
"She prefers halloumi" = 4,
"They love tofu" = 7
)|>
) style_tt(
i = c(3, 5, 9),
align = "c",
color = "white",
background = "gray",
bold = TRUE
)
mpg | cyl | disp | hp | drat | wt | qsec | vs |
---|---|---|---|---|---|---|---|
21 | 6 | 160 | 110 | 3.9 | 2.62 | 16.5 | 0 |
21 | 6 | 160 | 110 | 3.9 | 2.88 | 17 | 0 |
22.8 | 4 | 108 | 93 | 3.85 | 2.32 | 18.6 | 1 |
21.4 | 6 | 258 | 110 | 3.08 | 3.21 | 19.4 | 1 |
18.7 | 8 | 360 | 175 | 3.15 | 3.44 | 17 | 0 |
18.1 | 6 | 225 | 105 | 2.76 | 3.46 | 20.2 | 1 |
14.3 | 8 | 360 | 245 | 3.21 | 3.57 | 15.8 | 0 |
24.4 | 4 | 147 | 62 | 3.69 | 3.19 | 20 | 1 |
22.8 | 4 | 141 | 95 | 3.92 | 3.15 | 22.9 | 1 |
Automatic row groups
We can use the group_tt()
function to group rows and label them using spanners (almost) automatically. For example,
# subset and sort data
<- mtcars |>
df head(10) |>
sort_by(~am)
# draw table
tt(df) |> group_tt(i = df$am)
mpg | cyl | disp | hp | drat | wt | qsec | vs | am | gear | carb |
---|---|---|---|---|---|---|---|---|---|---|
21.4 | 6 | 258 | 110 | 3.08 | 3.21 | 19.4 | 1 | 0 | 3 | 1 |
18.7 | 8 | 360 | 175 | 3.15 | 3.44 | 17 | 0 | 0 | 3 | 2 |
18.1 | 6 | 225 | 105 | 2.76 | 3.46 | 20.2 | 1 | 0 | 3 | 1 |
14.3 | 8 | 360 | 245 | 3.21 | 3.57 | 15.8 | 0 | 0 | 3 | 4 |
24.4 | 4 | 147 | 62 | 3.69 | 3.19 | 20 | 1 | 0 | 4 | 2 |
22.8 | 4 | 141 | 95 | 3.92 | 3.15 | 22.9 | 1 | 0 | 4 | 2 |
19.2 | 6 | 168 | 123 | 3.92 | 3.44 | 18.3 | 1 | 0 | 4 | 4 |
21 | 6 | 160 | 110 | 3.9 | 2.62 | 16.5 | 0 | 1 | 4 | 4 |
21 | 6 | 160 | 110 | 3.9 | 2.88 | 17 | 0 | 1 | 4 | 4 |
22.8 | 4 | 108 | 93 | 3.85 | 2.32 | 18.6 | 1 | 1 | 4 | 1 |
Styling row groups
Calculating the location of rows can be cumbersome. Instead of doing this by hand, we can extract information from the table@group_index_i
S4 slot in the table object. Please be aware, however, that slot names are subject to change without warning in future versions of tinytable
.
library(magrittr)
tt(df) %>%
group_tt(i = df$am) %>%
style_tt(i = .@group_index_i, background = "pink")
mpg | cyl | disp | hp | drat | wt | qsec | vs | am | gear | carb |
---|---|---|---|---|---|---|---|---|---|---|
21.4 | 6 | 258 | 110 | 3.08 | 3.21 | 19.4 | 1 | 0 | 3 | 1 |
18.7 | 8 | 360 | 175 | 3.15 | 3.44 | 17 | 0 | 0 | 3 | 2 |
18.1 | 6 | 225 | 105 | 2.76 | 3.46 | 20.2 | 1 | 0 | 3 | 1 |
14.3 | 8 | 360 | 245 | 3.21 | 3.57 | 15.8 | 0 | 0 | 3 | 4 |
24.4 | 4 | 147 | 62 | 3.69 | 3.19 | 20 | 1 | 0 | 4 | 2 |
22.8 | 4 | 141 | 95 | 3.92 | 3.15 | 22.9 | 1 | 0 | 4 | 2 |
19.2 | 6 | 168 | 123 | 3.92 | 3.44 | 18.3 | 1 | 0 | 4 | 4 |
21 | 6 | 160 | 110 | 3.9 | 2.62 | 16.5 | 0 | 1 | 4 | 4 |
21 | 6 | 160 | 110 | 3.9 | 2.88 | 17 | 0 | 1 | 4 | 4 |
22.8 | 4 | 108 | 93 | 3.85 | 2.32 | 18.6 | 1 | 1 | 4 | 1 |
Columns
The syntax for column groups is very similar, but we use the j
argument instead. The named list specifies the labels to appear in column-spanning labels, and the values must be a vector of consecutive and non-overlapping integers that indicate which columns are associated to which labels:
tt(dat) |>
group_tt(
j = list(
"Hamburgers" = 1:3,
"Halloumi" = 4:5,
"Tofu" = 7))
Hamburgers | Halloumi | Tofu | |||||
---|---|---|---|---|---|---|---|
mpg | cyl | disp | hp | drat | wt | qsec | vs |
21 | 6 | 160 | 110 | 3.9 | 2.62 | 16.5 | 0 |
21 | 6 | 160 | 110 | 3.9 | 2.88 | 17 | 0 |
22.8 | 4 | 108 | 93 | 3.85 | 2.32 | 18.6 | 1 |
21.4 | 6 | 258 | 110 | 3.08 | 3.21 | 19.4 | 1 |
18.7 | 8 | 360 | 175 | 3.15 | 3.44 | 17 | 0 |
18.1 | 6 | 225 | 105 | 2.76 | 3.46 | 20.2 | 1 |
14.3 | 8 | 360 | 245 | 3.21 | 3.57 | 15.8 | 0 |
24.4 | 4 | 147 | 62 | 3.69 | 3.19 | 20 | 1 |
22.8 | 4 | 141 | 95 | 3.92 | 3.15 | 22.9 | 1 |
Here is a table with both row and column headers, as well as some styling:
<- mtcars[1:9, 1:8]
dat tt(dat) |>
group_tt(
i = list(
"I like (fake) hamburgers" = 3,
"She prefers halloumi" = 4,
"They love tofu" = 7
),j = list(
"Hamburgers" = 1:3,
"Halloumi" = 4:5,
"Tofu" = 7
)|>
) style_tt(
i = c(3, 5, 9),
align = "c",
background = "teal",
color = "white"
|>
) style_tt(i = -1, color = "teal")
Hamburgers | Halloumi | Tofu | |||||
---|---|---|---|---|---|---|---|
mpg | cyl | disp | hp | drat | wt | qsec | vs |
21 | 6 | 160 | 110 | 3.9 | 2.62 | 16.5 | 0 |
21 | 6 | 160 | 110 | 3.9 | 2.88 | 17 | 0 |
22.8 | 4 | 108 | 93 | 3.85 | 2.32 | 18.6 | 1 |
21.4 | 6 | 258 | 110 | 3.08 | 3.21 | 19.4 | 1 |
18.7 | 8 | 360 | 175 | 3.15 | 3.44 | 17 | 0 |
18.1 | 6 | 225 | 105 | 2.76 | 3.46 | 20.2 | 1 |
14.3 | 8 | 360 | 245 | 3.21 | 3.57 | 15.8 | 0 |
24.4 | 4 | 147 | 62 | 3.69 | 3.19 | 20 | 1 |
22.8 | 4 | 141 | 95 | 3.92 | 3.15 | 22.9 | 1 |
We can also stack several extra headers on top of one another:
tt(x) |>
group_tt(j = list("Foo" = 2:3, "Bar" = 5)) |>
group_tt(j = list("Hello" = 1:2, "World" = 4:5))
Hello | World | |||
---|---|---|---|---|
Foo | Bar | |||
mpg | cyl | disp | hp | drat |
21 | 6 | 160 | 110 | 3.9 |
21 | 6 | 160 | 110 | 3.9 |
22.8 | 4 | 108 | 93 | 3.85 |
21.4 | 6 | 258 | 110 | 3.08 |
Repeated column names
In some contexts, users wish to repeat the column names to treat them as group labels. Consider this dataset:
library(tinytable)
library(magrittr)
= data.frame(
dat Region = as.character(state.region),
State = row.names(state.x77),
1:3]) |>
state.x77[, sort_by(~ Region + State) |>
subset(Region %in% c("North Central", "Northeast"))
= do.call(rbind, by(dat, dat$Region, head, n = 3))
dat row.names(dat) = NULL
dat
Region State Population Income Illiteracy
1 North Central Illinois 11197 5107 0.9
2 North Central Indiana 5313 4458 0.7
3 North Central Iowa 2861 4628 0.5
4 Northeast Connecticut 3100 5348 1.1
5 Northeast Maine 1058 3694 0.7
6 Northeast Massachusetts 5814 4755 1.1
Here, we may want to repeat the column names for every region. The group_tt()
function does not support this directly, but it is easy to achieve this effect by:
- Insert column names as new rows in the data.
- Creat a row group variable (here:
region
) - Style the column names and group labels
# Format the numeric values early because repeating column names coerces all data to character
= format_tt(dat, digits = 1)
dat2
# Insert column names as new rows
= do.call(rbind, lapply(split(dat2, dat2$Region), \(d) {
dat2 rbind(as.list(colnames(d)), d)
}))
# Create row group variable
= which(dat2$Region == "Region")
idx $Region[idx] = dat2$Region[idx + 1]
dat2
# Draw table
%>%
dat2 subset(select = -Region) %>%
tt() %>%
group_tt(i = dat2$Region) %>%
style_tt(i = .@group_index_i + 1, background = "black", color = "white") %>%
style_tt(i = .@group_index_i, align = "c", color = "red") %>%
setNames(NULL)
State | Population | Income | Illiteracy |
Illinois | 11197 | 5107 | 0.9 |
Indiana | 5313 | 4458 | 0.7 |
Iowa | 2861 | 4628 | 0.5 |
State | Population | Income | Illiteracy |
Connecticut | 3100 | 5348 | 1.1 |
Maine | 1058 | 3694 | 0.7 |
Massachusetts | 5814 | 4755 | 1.1 |