Skip to content

Commit f83c427

Browse files
authored
Merge pull request #2129 from shannonhaughton/gt_group_list
Gt group list
2 parents cff38e6 + 76b883a commit f83c427

File tree

6 files changed

+113
-17
lines changed

6 files changed

+113
-17
lines changed

NEWS.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
# gt (development version)
22

3+
* Expand functionality of `gt_group()` to allow `gt_group` objects to be combined with `gt_tbls` (#2128)
4+
35
# gt 1.3.0
46

57
## New features

R/gt_group.R

Lines changed: 33 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -34,12 +34,12 @@
3434
#' can be printed independently and table separation (usually a page break)
3535
#' occurs between each of those.
3636
#'
37-
#' @param ... *One or more gt table data objects*
37+
#' @param ... *One or more gt table or gt_group data objects*
3838
#'
39-
#' `obj:<gt_tbl>` // (`optional`)
39+
#' `obj:<gt_tbl|gt_group>` // (`optional`)
4040
#'
41-
#' One or more **gt** table (`gt_tbl`) objects, typically generated via the
42-
#' [gt()] function.
41+
#' One or more **gt** table (`gt_tbl`) or (`gt_group`) objects, typically
42+
#' generated via the [gt()] function.
4343
#'
4444
#' @param .list *Alternative to `...`*
4545
#'
@@ -78,6 +78,35 @@ gt_group <- function(
7878
return(init_gt_group_list())
7979
}
8080

81+
# Check if there are any existing gt_groups in the list, if so flatten
82+
group_check <- sapply(gt_tbl_list, function(x)
83+
inherits(x, "gt_group"))
84+
85+
if (sum(group_check) > 0) {
86+
flattened_list <- lapply(gt_tbl_list, function(x) {
87+
if (inherits(x, "gt_group")) {
88+
no_tbls <- nrow(x[["gt_tbls"]])
89+
# pull out each gt_tbl
90+
gt_tables <- lapply(seq_len(no_tbls), function(i) {
91+
grp_pull(x, which = i)
92+
})
93+
} else {
94+
list(x)
95+
}
96+
})
97+
98+
gt_tbl_list <- unlist(flattened_list, recursive = FALSE)
99+
}
100+
101+
# Check that all items in the list are `gt_tbl` objects
102+
is_gt_tbl <- vapply(gt_tbl_list, FUN = inherits, FUN.VALUE = logical(1), "gt_tbl")
103+
104+
if (!all(is_gt_tbl)) {
105+
cli::cli_abort(
106+
"All objects supplied to {.fn gt_group} must be {.cls gt_tbl} or {.cls gt_group} objects."
107+
)
108+
}
109+
81110
# Initialize the `gt_group` object and create
82111
# an empty `gt_tbl_tbl` object
83112
gt_group <- init_gt_group_list()
@@ -86,9 +115,7 @@ gt_group <- function(
86115
#
87116
# Process gt tables and add records to the `gt_tbl_tbl` object
88117
#
89-
90118
for (i in seq_along(gt_tbl_list)) {
91-
92119
gt_tbl_tbl_i <- generate_gt_tbl_tbl_i(i = i, gt_tbl = gt_tbl_list[[i]])
93120
gt_tbl_tbl <- dplyr::bind_rows(gt_tbl_tbl, gt_tbl_tbl_i)
94121
}

man/gt_group.Rd

Lines changed: 4 additions & 4 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

man/rows_hide.Rd

Lines changed: 10 additions & 5 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

man/rows_unhide.Rd

Lines changed: 6 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

tests/testthat/test-gt_group.R

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,64 @@ test_that("gt_group() can be used to contain gt tables", {
4242
expect_s3_class(gt_tbls_1[["gt_tbl_options"]], "tbl_df")
4343
})
4444

45+
test_that("gt_group() can be used to contain gt tables and existing gt_groups", {
46+
47+
# Create two different `gt_tbl` table objects
48+
gt_tbl_1 <- gt(exibble)
49+
gt_tbl_2 <- gt(gtcars)
50+
51+
# Create a `gt_group` object with `gt_group()`
52+
gt_grp_1 <- gt_group(gt_tbl_1, gt_tbl_2)
53+
54+
# Create a new gt group from a list of all existing tables - including a gt_group
55+
gt_list <- list(gt_tbl_1, gt_tbl_2, gt_grp_1)
56+
57+
gt_tbls_1 <- gt_group(.list = gt_list)
58+
59+
# Expect that the `gt_tbls_1` object produced by `gt_group()`
60+
# has the 'gt_group' class
61+
expect_s3_class(gt_tbls_1, "gt_group")
62+
expect_type(gt_tbls_1, "list")
63+
64+
# The gt_group should contain 4 tables:
65+
# 2 individual tables + 1 group of 2 tables (flattened)
66+
expect_equal(nrow(gt_tbls_1[["gt_tbls"]]), 4L)
67+
68+
# Verify that the flattened tables match the originals
69+
expect_equal(grp_pull(gt_tbls_1, 1), gt_tbl_1)
70+
expect_equal(grp_pull(gt_tbls_1, 2), gt_tbl_2)
71+
expect_equal(grp_pull(gt_tbls_1, 3), grp_pull(gt_grp_1, 1))
72+
expect_equal(grp_pull(gt_tbls_1, 4), grp_pull(gt_grp_1, 2))
73+
74+
# Expect that `gt_group()` also works when passing gt_group objects via `...`
75+
gt_tbls_2 <- gt_group(gt_tbl_1, gt_grp_1)
76+
expect_s3_class(gt_tbls_2, "gt_group")
77+
expect_equal(nrow(gt_tbls_2[["gt_tbls"]]), 3L)
78+
79+
# Setting the option `.use_grp_opts` means that the internal
80+
# component of similar naming is set to that logical value
81+
# Create a `gt_group` object with `gt_group()`
82+
gt_tbls_3 <- gt_group(.list = gt_list, .use_grp_opts = TRUE)
83+
expect_true(gt_tbls_3[["use_grp_opts"]])
84+
gt_tbls_4 <- gt_group(.list = gt_list, .use_grp_opts = FALSE)
85+
expect_false(gt_tbls_4[["use_grp_opts"]])
86+
87+
# Not setting it means it will be FALSE by default
88+
gt_tbls_5 <- gt_group(.list = gt_list)
89+
expect_false(gt_tbls_5[["use_grp_opts"]])
90+
91+
# Expect specific components inside of a 'gt_group' object
92+
expect_named(
93+
gt_tbls_1,
94+
c("gt_tbls", "gt_tbl_options", "use_grp_opts")
95+
)
96+
97+
# Expect that the 'gt_tbls' and `gt_tbl_options` objects inside of
98+
# 'gt_group' are both tibbles
99+
expect_s3_class(gt_tbls_1[["gt_tbls"]], "tbl_df")
100+
expect_s3_class(gt_tbls_1[["gt_tbl_options"]], "tbl_df")
101+
})
102+
45103
test_that("grp_pull() can be used to extract a table from a group", {
46104

47105
# Create two different `gt_tbl` table objects

0 commit comments

Comments
 (0)