diff --git a/NEWS.md b/NEWS.md index f40bd8e4a..a562d0474 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,5 +1,11 @@ # cards 0.9.0.9000 +## Bug Fixes + +* Fixed a bug in `print.compare_ard()` where the rows present in `x` but not in `y` were announced and then not printed. (#605, @malanbos) + +* `print.compare_ard()` now prints its tables through the ARD print method rather than coercing them with `as.data.frame()`. Scalar list-column values (e.g. `group1_level`, `variable_level`, `stat`) are shown rather than collapsed, and long tables are truncated with the withheld row count reported in the footer. (#605) + # cards 0.9.0 ## Performance diff --git a/R/print.R b/R/print.R index 4b6403410..306b2ea4a 100644 --- a/R/print.R +++ b/R/print.R @@ -172,6 +172,10 @@ tbl_format_setup.card <- function(x, width = NULL, ...) { #' @export #' @rdname print.card print.compare_ard <- function(x, ...) { + # sub-headers sit directly beneath their section rule; the div closes itself + # when this function exits + cli::cli_div(theme = list(h3 = list("margin-top" = 0))) + # print comparison details --------------------------------------------------- cli::cli_inform("The comparison {.arg keys} are {.val {x$keys}}.") cli::cli_inform("The comparison columns are {.val {x$columns}}.") @@ -182,13 +186,13 @@ print.compare_ard <- function(x, ...) { cli::cli_alert_success("No rows in {.arg x} that do not appear in {.arg y}.") } else { cli::cli_h3("Rows in {.arg x} that do not appear in {.arg y}.") - as.data.frame(x$rows_in_x_not_y) |> print() + print(x$rows_in_x_not_y) } if (nrow(x$rows_in_y_not_x) == 0L) { cli::cli_alert_success("No rows in {.arg y} that do not appear in {.arg x}.") } else { cli::cli_h3("Rows in {.arg y} that do not appear in {.arg x}.") - as.data.frame(x$rows_in_y_not_x) |> print() + print(x$rows_in_y_not_x) } # print comparison results --------------------------------------------------- @@ -199,9 +203,7 @@ print.compare_ard <- function(x, ...) { next } cli::cli_alert_warning("Differences found in column {.val {names(x$comparison[i])}} for {.val {nrow(x$comparison[[i]])}} rows.") - as.data.frame(x$comparison[[i]]) |> - utils::head(n = 10) |> - print() + print(x$comparison[[i]]) } # return input invisibly ----------------------------------------------------- diff --git a/tests/testthat/_snaps/print.md b/tests/testthat/_snaps/print.md index 612ce604d..f2bb1d727 100644 --- a/tests/testthat/_snaps/print.md +++ b/tests/testthat/_snaps/print.md @@ -190,19 +190,20 @@ The comparison columns are "stat_label" and "stat". -- Mis-matched Rows ------------------------------------------------------------ - -- Rows in `x` that do not appear in `y`. Output - group1 group1_level variable variable_level stat_name - 1 ARM Placebo AGEGR1 >80 n - 2 ARM Placebo AGEGR1 >80 N - 3 ARM Placebo AGEGR1 >80 p - 4 ARM Xanomeline High Dose AGEGR1 >80 n - 5 ARM Xanomeline High Dose AGEGR1 >80 N - 6 ARM Xanomeline High Dose AGEGR1 >80 p - 7 ARM Xanomeline Low Dose AGEGR1 >80 n - 8 ARM Xanomeline Low Dose AGEGR1 >80 N - 9 ARM Xanomeline Low Dose AGEGR1 >80 p + # An ARD data frame: 9 x 5 + group1 group1_level variable variable_level stat_name + + 1 ARM Placebo AGEGR1 >80 n + 2 ARM Placebo AGEGR1 >80 N + 3 ARM Placebo AGEGR1 >80 p + 4 ARM Xanomeline High Dose AGEGR1 >80 n + 5 ARM Xanomeline High Dose AGEGR1 >80 N + 6 ARM Xanomeline High Dose AGEGR1 >80 p + 7 ARM Xanomeline Low Dose AGEGR1 >80 n + 8 ARM Xanomeline Low Dose AGEGR1 >80 N + 9 ARM Xanomeline Low Dose AGEGR1 >80 p Message v No rows in `y` that do not appear in `x`. @@ -210,28 +211,21 @@ v No differences found in column "stat_label". ! Differences found in column "stat" for 12 rows. Output - group1 group1_level variable variable_level stat_name stat.x - 1 ARM Placebo AGEGR1 65-80 N 86 - 2 ARM Placebo AGEGR1 65-80 p 0.4883721 - 3 ARM Placebo AGEGR1 <65 N 86 - 4 ARM Placebo AGEGR1 <65 p 0.1627907 - 5 ARM Xanomeline High Dose AGEGR1 65-80 N 84 - 6 ARM Xanomeline High Dose AGEGR1 65-80 p 0.6547619 - 7 ARM Xanomeline High Dose AGEGR1 <65 N 84 - 8 ARM Xanomeline High Dose AGEGR1 <65 p 0.1309524 - 9 ARM Xanomeline Low Dose AGEGR1 65-80 N 84 - 10 ARM Xanomeline Low Dose AGEGR1 65-80 p 0.5595238 - stat.y difference - 1 56 Mean relative difference: 0.3488372 - 2 0.75 Mean relative difference: 0.5357143 - 3 56 Mean relative difference: 0.3488372 - 4 0.25 Mean relative difference: 0.5357143 - 5 66 Mean relative difference: 0.2142857 - 6 0.8333333 Mean relative difference: 0.2727273 - 7 66 Mean relative difference: 0.2142857 - 8 0.1666667 Mean relative difference: 0.2727273 - 9 55 Mean relative difference: 0.3452381 - 10 0.8545455 Mean relative difference: 0.5272727 + # An ARD data frame: 12 x 8 + group1 group1_level variable variable_level stat_name stat.x stat.y difference + + 1 ARM Placebo AGEGR1 65-80 N 86 56 Mean relative difference: 0.3488372 + 2 ARM Placebo AGEGR1 65-80 p 0.488 0.75 Mean relative difference: 0.5357143 + 3 ARM Placebo AGEGR1 <65 N 86 56 Mean relative difference: 0.3488372 + 4 ARM Placebo AGEGR1 <65 p 0.163 0.25 Mean relative difference: 0.5357143 + 5 ARM Xanomeline High Dose AGEGR1 65-80 N 84 66 Mean relative difference: 0.2142857 + 6 ARM Xanomeline High Dose AGEGR1 65-80 p 0.655 0.833 Mean relative difference: 0.2727273 + 7 ARM Xanomeline High Dose AGEGR1 <65 N 84 66 Mean relative difference: 0.2142857 + 8 ARM Xanomeline High Dose AGEGR1 <65 p 0.131 0.167 Mean relative difference: 0.2727273 + 9 ARM Xanomeline Low Dose AGEGR1 65-80 N 84 55 Mean relative difference: 0.3452381 + 10 ARM Xanomeline Low Dose AGEGR1 65-80 p 0.560 0.855 Mean relative difference: 0.5272727 + 11 ARM Xanomeline Low Dose AGEGR1 <65 N 84 55 Mean relative difference: 0.3452381 + 12 ARM Xanomeline Low Dose AGEGR1 <65 p 0.0952 0.145 Mean relative difference: 0.5272727 --- @@ -243,45 +237,133 @@ -- Mis-matched Rows ------------------------------------------------------------ v No rows in `x` that do not appear in `y`. - -- Rows in `y` that do not appear in `x`. Output - group1 group1_level variable variable_level stat_name - 1 ARM Placebo AGEGR1 >80 n - 2 ARM Placebo AGEGR1 >80 N - 3 ARM Placebo AGEGR1 >80 p - 4 ARM Xanomeline High Dose AGEGR1 >80 n - 5 ARM Xanomeline High Dose AGEGR1 >80 N - 6 ARM Xanomeline High Dose AGEGR1 >80 p - 7 ARM Xanomeline Low Dose AGEGR1 >80 n - 8 ARM Xanomeline Low Dose AGEGR1 >80 N - 9 ARM Xanomeline Low Dose AGEGR1 >80 p + # An ARD data frame: 9 x 5 + group1 group1_level variable variable_level stat_name + + 1 ARM Placebo AGEGR1 >80 n + 2 ARM Placebo AGEGR1 >80 N + 3 ARM Placebo AGEGR1 >80 p + 4 ARM Xanomeline High Dose AGEGR1 >80 n + 5 ARM Xanomeline High Dose AGEGR1 >80 N + 6 ARM Xanomeline High Dose AGEGR1 >80 p + 7 ARM Xanomeline Low Dose AGEGR1 >80 n + 8 ARM Xanomeline Low Dose AGEGR1 >80 N + 9 ARM Xanomeline Low Dose AGEGR1 >80 p Message -- Comparison Results ---------------------------------------------------------- v No differences found in column "stat_label". ! Differences found in column "stat" for 12 rows. Output - group1 group1_level variable variable_level stat_name stat.x - 1 ARM Placebo AGEGR1 65-80 N 56 - 2 ARM Placebo AGEGR1 65-80 p 0.75 - 3 ARM Placebo AGEGR1 <65 N 56 - 4 ARM Placebo AGEGR1 <65 p 0.25 - 5 ARM Xanomeline High Dose AGEGR1 65-80 N 66 - 6 ARM Xanomeline High Dose AGEGR1 65-80 p 0.8333333 - 7 ARM Xanomeline High Dose AGEGR1 <65 N 66 - 8 ARM Xanomeline High Dose AGEGR1 <65 p 0.1666667 - 9 ARM Xanomeline Low Dose AGEGR1 65-80 N 55 - 10 ARM Xanomeline Low Dose AGEGR1 65-80 p 0.8545455 - stat.y difference - 1 86 Mean relative difference: 0.5357143 - 2 0.4883721 Mean relative difference: 0.3488372 - 3 86 Mean relative difference: 0.5357143 - 4 0.1627907 Mean relative difference: 0.3488372 - 5 84 Mean relative difference: 0.2727273 - 6 0.6547619 Mean relative difference: 0.2142857 - 7 84 Mean relative difference: 0.2727273 - 8 0.1309524 Mean relative difference: 0.2142857 - 9 84 Mean relative difference: 0.5272727 - 10 0.5595238 Mean relative difference: 0.3452381 + # An ARD data frame: 12 x 8 + group1 group1_level variable variable_level stat_name stat.x stat.y difference + + 1 ARM Placebo AGEGR1 65-80 N 56 86 Mean relative difference: 0.5357143 + 2 ARM Placebo AGEGR1 65-80 p 0.75 0.488 Mean relative difference: 0.3488372 + 3 ARM Placebo AGEGR1 <65 N 56 86 Mean relative difference: 0.5357143 + 4 ARM Placebo AGEGR1 <65 p 0.25 0.163 Mean relative difference: 0.3488372 + 5 ARM Xanomeline High Dose AGEGR1 65-80 N 66 84 Mean relative difference: 0.2727273 + 6 ARM Xanomeline High Dose AGEGR1 65-80 p 0.833 0.655 Mean relative difference: 0.2142857 + 7 ARM Xanomeline High Dose AGEGR1 <65 N 66 84 Mean relative difference: 0.2727273 + 8 ARM Xanomeline High Dose AGEGR1 <65 p 0.167 0.131 Mean relative difference: 0.2142857 + 9 ARM Xanomeline Low Dose AGEGR1 65-80 N 55 84 Mean relative difference: 0.5272727 + 10 ARM Xanomeline Low Dose AGEGR1 65-80 p 0.855 0.560 Mean relative difference: 0.3452381 + 11 ARM Xanomeline Low Dose AGEGR1 <65 N 55 84 Mean relative difference: 0.5272727 + 12 ARM Xanomeline Low Dose AGEGR1 <65 p 0.145 0.0952 Mean relative difference: 0.3452381 + +# print.compare_ard() prints both mis-matched row blocks + + Code + compare_ard(ard_no_high, ard_no_low) + Message + The comparison `keys` are "group1", "group1_level", "variable", "variable_level", and "stat_name". + The comparison columns are "stat_label" and "stat". + + -- Mis-matched Rows ------------------------------------------------------------ + -- Rows in `x` that do not appear in `y`. + Output + # An ARD data frame: 9 x 5 + group1 group1_level variable variable_level stat_name + + 1 ARM Placebo AGEGR1 <65 n + 2 ARM Placebo AGEGR1 <65 N + 3 ARM Placebo AGEGR1 <65 p + 4 ARM Xanomeline High Dose AGEGR1 <65 n + 5 ARM Xanomeline High Dose AGEGR1 <65 N + 6 ARM Xanomeline High Dose AGEGR1 <65 p + 7 ARM Xanomeline Low Dose AGEGR1 <65 n + 8 ARM Xanomeline Low Dose AGEGR1 <65 N + 9 ARM Xanomeline Low Dose AGEGR1 <65 p + Message + -- Rows in `y` that do not appear in `x`. + Output + # An ARD data frame: 9 x 5 + group1 group1_level variable variable_level stat_name + + 1 ARM Placebo AGEGR1 >80 n + 2 ARM Placebo AGEGR1 >80 N + 3 ARM Placebo AGEGR1 >80 p + 4 ARM Xanomeline High Dose AGEGR1 >80 n + 5 ARM Xanomeline High Dose AGEGR1 >80 N + 6 ARM Xanomeline High Dose AGEGR1 >80 p + 7 ARM Xanomeline Low Dose AGEGR1 >80 n + 8 ARM Xanomeline Low Dose AGEGR1 >80 N + 9 ARM Xanomeline Low Dose AGEGR1 >80 p + Message + + -- Comparison Results ---------------------------------------------------------- + v No differences found in column "stat_label". + ! Differences found in column "stat" for 6 rows. + Output + # An ARD data frame: 6 x 8 + group1 group1_level variable variable_level stat_name stat.x stat.y difference + + 1 ARM Placebo AGEGR1 65-80 N 56 72 Mean relative difference: 0.2857143 + 2 ARM Placebo AGEGR1 65-80 p 0.75 0.583 Mean relative difference: 0.2222222 + 3 ARM Xanomeline High Dose AGEGR1 65-80 N 66 73 Mean relative difference: 0.1060606 + 4 ARM Xanomeline High Dose AGEGR1 65-80 p 0.833 0.753 Mean relative difference: 0.09589041 + 5 ARM Xanomeline Low Dose AGEGR1 65-80 N 55 76 Mean relative difference: 0.3818182 + 6 ARM Xanomeline Low Dose AGEGR1 65-80 p 0.855 0.618 Mean relative difference: 0.2763158 + +# print.compare_ard() truncates long mis-matched row blocks + + Code + compare_ard(ard, ard_two_sites) + Message + The comparison `keys` are "variable", "variable_level", and "stat_name". + The comparison columns are "stat_label" and "stat". + + -- Mis-matched Rows ------------------------------------------------------------ + -- Rows in `x` that do not appear in `y`. + Output + # An ARD data frame: 45 x 3 + variable variable_level stat_name + + 1 SITEID 702 n + 2 SITEID 702 N + 3 SITEID 702 p + 4 SITEID 704 n + 5 SITEID 704 N + 6 SITEID 704 p + 7 SITEID 705 n + 8 SITEID 705 N + 9 SITEID 705 p + 10 SITEID 706 n + # i 35 more rows + Message + v No rows in `y` that do not appear in `x`. + + -- Comparison Results ---------------------------------------------------------- + v No differences found in column "stat_label". + ! Differences found in column "stat" for 4 rows. + Output + # An ARD data frame: 4 x 6 + variable variable_level stat_name stat.x stat.y difference + + 1 SITEID 701 N 254 59 Mean relative difference: 0.7677165 + 2 SITEID 701 p 0.161 0.695 Mean relative difference: 3.305085 + 3 SITEID 703 N 254 59 Mean relative difference: 0.7677165 + 4 SITEID 703 p 0.0709 0.305 Mean relative difference: 3.305085 diff --git a/tests/testthat/test-print.R b/tests/testthat/test-print.R index 5e6b87efd..fea08dd7a 100644 --- a/tests/testthat/test-print.R +++ b/tests/testthat/test-print.R @@ -63,6 +63,10 @@ test_that("print.card() keeps non-NULL warning/error columns when narrow", { }) test_that("print.compare_ard() works", { + # widen the console so the comparison tables print in one piece rather than + # being split into column chunks by `print.data.frame()` + withr::local_options(width = 200) + ard <- ard_tabulate(ADSL, by = "ARM", variables = "AGEGR1") # equal ARDs @@ -88,3 +92,75 @@ test_that("print.compare_ard() works", { compare_ard(ard_subset, ard) ) }) + +test_that("print.compare_ard() prints both mis-matched row blocks", { + # widen the console so the comparison tables print in one piece rather than + # being split into column chunks by `print.data.frame()` + withr::local_options(width = 200) + + # each ARD holds an age group the other does not, so both blocks print + ard_no_high <- + ard_tabulate( + dplyr::filter(ADSL, AGEGR1 != ">80"), + by = "ARM", + variables = "AGEGR1" + ) + ard_no_low <- + ard_tabulate( + dplyr::filter(ADSL, AGEGR1 != "<65"), + by = "ARM", + variables = "AGEGR1" + ) + + expect_snapshot( + compare_ard(ard_no_high, ard_no_low) + ) +}) + +test_that("print.compare_ard() prints the mis-matched rows themselves (#605)", { + ard <- ard_tabulate(ADSL, by = "ARM", variables = "AGEGR1") + ard_subset <- + ard_tabulate( + dplyr::filter(ADSL, AGEGR1 != ">80"), + by = "ARM", + variables = "AGEGR1" + ) + + # the ">80" rows appear in only one of the two ARDs, so they are never part + # of the comparison tables -- seeing ">80" on stdout means the mis-matched + # row block itself printed. `cli` writes to stderr, so it is not captured + # here. Asserted outside of a snapshot so that regenerating the snapshots + # cannot quietly accept the output going missing again. + expect_output( + print(compare_ard(ard, ard_subset)), + ">80", + fixed = TRUE + ) + expect_output( + print(compare_ard(ard_subset, ard)), + ">80", + fixed = TRUE + ) +}) + +test_that("print.compare_ard() truncates long mis-matched row blocks", { + # widen the console so the comparison tables print in one piece rather than + # being split into column chunks by `print.data.frame()` + withr::local_options(width = 200) + + # 17 sites x 3 statistics, of which only two sites survive the filter, so the + # block is far longer than the console can hold and is truncated by the ARD + # print method with the withheld row count in the footer + ard <- ard_tabulate(ADSL, variables = "SITEID") + ard_two_sites <- + ard_tabulate( + dplyr::filter(ADSL, SITEID %in% c("701", "703")), + variables = "SITEID" + ) + + expect_equal(nrow(compare_ard(ard, ard_two_sites)$rows_in_x_not_y), 45L) + + expect_snapshot( + compare_ard(ard, ard_two_sites) + ) +})