From ec0104fbee9644e2c2fc812180781be971d0a10c Mon Sep 17 00:00:00 2001 From: Emily de la Rua <59304861+edelarua@users.noreply.github.com> Date: Mon, 27 Nov 2023 17:14:42 -0500 Subject: [PATCH 1/2] Add support for multiple risk difference columns (#1143) Fixes #1142 --- NEWS.md | 1 + R/riskdiff.R | 32 ++++++++++++++++------ man/add_riskdiff.Rd | 12 +++++--- tests/testthat/_snaps/count_occurrences.md | 18 ++++++++++++ tests/testthat/test-count_occurrences.R | 13 +++++++++ 5 files changed, 63 insertions(+), 13 deletions(-) diff --git a/NEWS.md b/NEWS.md index 19496c2b8c..cded8fbe56 100644 --- a/NEWS.md +++ b/NEWS.md @@ -18,6 +18,7 @@ * Added `annot_coxph_ref_lbls` parameter to `g_km` to enable printing the reference group in table labels when `annot_coxph = TRUE`. * Added `x_lab` parameter to `g_lineplot` to customize x-axis label. * Remove 25% padding of y-axis in `g_lineplot`. +* Added support for creating multiple risk difference columns, each comparing to a single comparison group. Multiple comparison groups can be specified as a vector via the `arm_y` argument. ### Bug Fixes * Fixed bug in `decorate_grob` preventing text wrapping from accounting for font size. diff --git a/R/riskdiff.R b/R/riskdiff.R index 8a86be6dce..d1be5816da 100644 --- a/R/riskdiff.R +++ b/R/riskdiff.R @@ -8,8 +8,11 @@ #' `riskdiff` to `TRUE` in all following analyze function calls. #' #' @param arm_x (`character`)\cr Name of reference arm to use in risk difference calculations. -#' @param arm_y (`character`)\cr Name of arm to compare to reference arm in risk difference calculations. -#' @param col_label (`character`)\cr Label to use when rendering the risk difference column within the table. +#' @param arm_y (`character`)\cr Names of one or more arms to compare to reference arm in risk difference +#' calculations. A new column will be added for each value of `arm_y`. +#' @param col_label (`character`)\cr Labels to use when rendering the risk difference column within the table. +#' If more than one comparison arm is specified in `arm_y`, default labels will specify which two arms are +#' being compared (reference arm vs. comparison arm). #' @param pct (`flag`)\cr whether output should be returned as percentages. Defaults to `TRUE`. #' #' @return A closure suitable for use as a split function (`split_fun`) within [rtables::split_cols_by()] @@ -22,7 +25,7 @@ #' adae$AESEV <- factor(adae$AESEV) #' #' lyt <- basic_table() %>% -#' split_cols_by("ARMCD", split_fun = add_riskdiff(arm_x = "ARM A", arm_y = "ARM B")) %>% +#' split_cols_by("ARMCD", split_fun = add_riskdiff(arm_x = "ARM A", arm_y = c("ARM B", "ARM C"))) %>% #' count_occurrences_by_grade( #' var = "AESEV", #' riskdiff = TRUE @@ -34,13 +37,24 @@ #' @export add_riskdiff <- function(arm_x, arm_y, - col_label = "Risk Difference (%) (95% CI)", + col_label = paste0( + "Risk Difference (%) (95% CI)", if (length(arm_y) > 1) paste0("\n", arm_x, " vs. ", arm_y) + ), pct = TRUE) { - sapply(c(arm_x, arm_y, col_label), checkmate::assert_character, len = 1) - combodf <- tibble::tribble( - ~valname, ~label, ~levelcombo, ~exargs, - paste("riskdiff", arm_x, arm_y, sep = "_"), col_label, c(arm_x, arm_y), list() - ) + checkmate::assert_character(arm_x, len = 1) + checkmate::assert_character(arm_y, min.len = 1) + checkmate::assert_character(col_label, len = length(arm_y)) + + combodf <- tibble::tribble(~valname, ~label, ~levelcombo, ~exargs) + for (i in seq_len(length(arm_y))) { + combodf <- rbind( + combodf, + tibble::tribble( + ~valname, ~label, ~levelcombo, ~exargs, + paste("riskdiff", arm_x, arm_y[i], sep = "_"), col_label[i], c(arm_x, arm_y[i]), list() + ) + ) + } if (pct) combodf$valname <- paste0(combodf$valname, "_pct") add_combo_levels(combodf) } diff --git a/man/add_riskdiff.Rd b/man/add_riskdiff.Rd index 2bdfaead68..ba8a8931ac 100644 --- a/man/add_riskdiff.Rd +++ b/man/add_riskdiff.Rd @@ -7,16 +7,20 @@ add_riskdiff( arm_x, arm_y, - col_label = "Risk Difference (\%) (95\% CI)", + col_label = paste0("Risk Difference (\%) (95\% CI)", if (length(arm_y) > 1) + paste0("\\n", arm_x, " vs. ", arm_y)), pct = TRUE ) } \arguments{ \item{arm_x}{(\code{character})\cr Name of reference arm to use in risk difference calculations.} -\item{arm_y}{(\code{character})\cr Name of arm to compare to reference arm in risk difference calculations.} +\item{arm_y}{(\code{character})\cr Names of one or more arms to compare to reference arm in risk difference +calculations. A new column will be added for each value of \code{arm_y}.} -\item{col_label}{(\code{character})\cr Label to use when rendering the risk difference column within the table.} +\item{col_label}{(\code{character})\cr Labels to use when rendering the risk difference column within the table. +If more than one comparison arm is specified in \code{arm_y}, default labels will specify which two arms are +being compared (reference arm vs. comparison arm).} \item{pct}{(\code{flag})\cr whether output should be returned as percentages. Defaults to \code{TRUE}.} } @@ -37,7 +41,7 @@ adae <- tern_ex_adae adae$AESEV <- factor(adae$AESEV) lyt <- basic_table() \%>\% - split_cols_by("ARMCD", split_fun = add_riskdiff(arm_x = "ARM A", arm_y = "ARM B")) \%>\% + split_cols_by("ARMCD", split_fun = add_riskdiff(arm_x = "ARM A", arm_y = c("ARM B", "ARM C"))) \%>\% count_occurrences_by_grade( var = "AESEV", riskdiff = TRUE diff --git a/tests/testthat/_snaps/count_occurrences.md b/tests/testthat/_snaps/count_occurrences.md index 1f2a4eb280..167e4e1ba4 100644 --- a/tests/testthat/_snaps/count_occurrences.md +++ b/tests/testthat/_snaps/count_occurrences.md @@ -283,3 +283,21 @@ MEDIUM 5 (7.8%) 2 (3.0%) 1 (1.6%) 4.8 (-2.9 - 12.6) 2 (2.6%) 3 (4.7%) 2 (4.4%) -2.1 (-8.4 - 4.1) 3 (5.0%) 4 (8.7%) 1 (1.8%) -3.7 (-13.5 - 6.1) HIGH 2 (3.1%) 5 (7.5%) 5 (8.1%) -4.3 (-11.9 - 3.3) 2 (2.6%) 5 (7.8%) 3 (6.7%) -5.2 (-12.7 - 2.2) 0 2 (4.3%) 3 (5.5%) -4.3 (-10.2 - 1.5) +--- + + Code + res + Output + Risk Difference (%) (95% CI) Risk Difference (%) (95% CI) + A: Drug X B: Placebo C: Combination A: Drug X vs. B: Placebo A: Drug X vs. C: Combination + (N=202) (N=177) (N=162) (N=379) (N=364) + ———————————————————————————————————————————————————————————————————————————————————————————————————————————————— + F + LOW 12 (5.9%) 11 (6.2%) 10 (6.2%) -0.3 (-5.1 - 4.6) -0.2 (-5.2 - 4.7) + MEDIUM 11 (5.4%) 13 (7.3%) 10 (6.2%) -1.9 (-6.9 - 3.1) -0.7 (-5.6 - 4.1) + HIGH 10 (5.0%) 7 (4.0%) 7 (4.3%) 1.0 (-3.2 - 5.1) 0.6 (-3.7 - 5.0) + M + LOW 12 (5.9%) 5 (2.8%) 6 (3.7%) 3.1 (-1.0 - 7.2) 2.2 (-2.1 - 6.6) + MEDIUM 10 (5.0%) 9 (5.1%) 4 (2.5%) -0.1 (-4.5 - 4.3) 2.5 (-1.3 - 6.3) + HIGH 4 (2.0%) 12 (6.8%) 11 (6.8%) -4.8 (-9.0 - -0.6) -4.8 (-9.1 - -0.5) + diff --git a/tests/testthat/test-count_occurrences.R b/tests/testthat/test-count_occurrences.R index eb0f75df63..35994b913e 100644 --- a/tests/testthat/test-count_occurrences.R +++ b/tests/testthat/test-count_occurrences.R @@ -272,4 +272,17 @@ testthat::test_that("summarize_occurrences works as expected with risk differenc res <- testthat::expect_silent(result) testthat::expect_snapshot(res) + + # Multiple comparison groups + result <- basic_table(show_colcounts = TRUE) %>% + split_cols_by("ARM", split_fun = add_riskdiff("A: Drug X", c("B: Placebo", "C: Combination"))) %>% + split_rows_by("SEX", child_labels = "visible") %>% + summarize_occurrences( + var = "BMRKR2", + riskdiff = TRUE + ) %>% + build_table(tern_ex_adae) + + res <- testthat::expect_silent(result) + testthat::expect_snapshot(res) }) From 2203bc7325492c9f8bd1835b88a55c51f9173c73 Mon Sep 17 00:00:00 2001 From: edelarua Date: Mon, 27 Nov 2023 22:15:45 +0000 Subject: [PATCH 2/2] [skip actions] Bump version to 0.9.2.9019 --- DESCRIPTION | 2 +- NEWS.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/DESCRIPTION b/DESCRIPTION index 01e693db79..29b6411c69 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -1,6 +1,6 @@ Package: tern Title: Create Common TLGs Used in Clinical Trials -Version: 0.9.2.9018 +Version: 0.9.2.9019 Date: 2023-11-27 Authors@R: c( person("Joe", "Zhu", , "joe.zhu@roche.com", role = c("aut", "cre")), diff --git a/NEWS.md b/NEWS.md index cded8fbe56..bf901875e2 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,4 +1,4 @@ -# tern 0.9.2.9018 +# tern 0.9.2.9019 ### New Features * Added `ref_group_position` function to place the reference group facet last, first or at a certain position.