group – tinytable (original) (raw)
Groups and labels
library(tinytable)
options(tinytable_tt_digits = 3)
options(tinytable_theme_placement_latex_float = "H")
x <- mtcars[1:4, 1:5]
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:
dat <- mtcars[1:9, 1:8]
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
df <- mtcars |>
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 use the “groupi” shortcut to style rows.
library(magrittr)
tt(df) %>%
group_tt(i = df$am) %>%
style_tt(i = "groupi", 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:
dat <- mtcars[1:9, 1:8]
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 |
Column names with delimiters
Group labels can be specified using column names with delimiters. For example, some of the columns in this data frame have group identifiers. Note that the first column does not have a group identifier, and that the last column has a group identifier but no column name.
dat <- data.frame(
id = 1,
A_a1 = 2,
A_a2 = "3",
B_b1 = 4,
B_b2 = 5,
C_ = 6)
tt(dat) |> group_tt(j = "_")
| | A | B | C | | | | | ---- | -- | -- | -- | -- | - | | id | a1 | a2 | b1 | b2 | | | 1 | 2 | 3 | 4 | 5 | 6 |
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)
dat = data.frame(
Region = as.character(state.region),
State = row.names(state.x77),
state.x77[, 1:3]) |>
sort_by(~ Region + State) |>
subset(Region %in% c("North Central", "Northeast"))
dat = do.call(rbind, by(dat, dat$Region, head, n = 3))
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
Normally, we would call style_tt(i = "groupi")
to style the row groups, but here we need the actual indices to also style one row below the groups. We can use the @group_index_i
slot to get the indices of the row groups.
# Format the numeric values early because repeating column names coerces all data to character
dat2 = format_tt(dat, digits = 1)
# Insert column names as new rows
dat2 = do.call(rbind, lapply(split(dat2, dat2$Region), \(d) {
rbind(as.list(colnames(d)), d)
}))
# Create row group variable
idx = which(dat2$Region == "Region")
dat2$Region[idx] = dat2$Region[idx + 1]
# 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 |