diff --git a/DESCRIPTION b/DESCRIPTION index 7c76cda740..01a35b04ed 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -1,7 +1,7 @@ Package: tern Title: Create Common TLGs Used in Clinical Trials -Version: 0.9.6.9016 -Date: 2024-11-20 +Version: 0.9.6.9017 +Date: 2024-12-03 Authors@R: c( person("Joe", "Zhu", , "joe.zhu@roche.com", role = c("aut", "cre")), person("Daniel", "Sabanés Bové", , "daniel.sabanes_bove@roche.com", role = "aut"), diff --git a/NEWS.md b/NEWS.md index 1fb0cc7b09..7eb8da9473 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,4 +1,4 @@ -# tern 0.9.6.9016 +# tern 0.9.6.9017 ### Enhancements * Added the `denom` parameter to `s_count_cumulative()`, `s_count_missed_doses()`, and `s_count_occurrences_by_grade()`. diff --git a/R/summarize_glm_count.R b/R/summarize_glm_count.R index 84c9e7c00b..31e68b1607 100644 --- a/R/summarize_glm_count.R +++ b/R/summarize_glm_count.R @@ -84,6 +84,20 @@ NULL #' rate = "Rate", rate_ci = "Rate CI", rate_ratio = "Rate Ratio", #' rate_ratio_ci = "Rate Ratio CI", pval = "p value" #' ) +#' ) %>% +#' summarize_glm_count( +#' vars = "AVAL", +#' variables = list(arm = "ARM", offset = "lgTMATRSK", covariates = c("REGION1")), +#' conf_level = 0.95, +#' distribution = "negbin", +#' rate_mean_method = "emmeans", +#' var_labels = "Adjusted (NB) exacerbation rate (per year)", +#' table_names = "adjNB", +#' .stats = c("rate", "rate_ci", "rate_ratio", "rate_ratio_ci", "pval"), +#' .labels = c( +#' rate = "Rate", rate_ci = "Rate CI", rate_ratio = "Rate Ratio", +#' rate_ratio_ci = "Rate Ratio CI", pval = "p value" +#' ) #' ) #' #' build_table(lyt = lyt, df = anl) @@ -322,7 +336,6 @@ h_glm_poisson <- function(.var, weights) { arm <- variables$arm covariates <- variables$covariates - offset <- .df_row[[variables$offset]] formula <- stats::as.formula(paste0( .var, " ~ ", @@ -332,12 +345,21 @@ h_glm_poisson <- function(.var, arm )) - glm_fit <- stats::glm( - formula = formula, - offset = offset, - data = .df_row, - family = stats::poisson(link = "log") - ) + if (is.null(variables$offset)) { + glm_fit <- stats::glm( + formula = formula, + data = .df_row, + family = stats::poisson(link = "log") + ) + } else { + offset <- .df_row[[variables$offset]] + glm_fit <- stats::glm( + formula = formula, + offset = offset, + data = .df_row, + family = stats::poisson(link = "log") + ) + } emmeans_fit <- emmeans::emmeans( glm_fit, @@ -366,7 +388,6 @@ h_glm_quasipoisson <- function(.var, weights) { arm <- variables$arm covariates <- variables$covariates - offset <- .df_row[[variables$offset]] formula <- stats::as.formula(paste0( .var, " ~ ", @@ -376,13 +397,21 @@ h_glm_quasipoisson <- function(.var, arm )) - glm_fit <- stats::glm( - formula = formula, - offset = offset, - data = .df_row, - family = stats::quasipoisson(link = "log") - ) - + if (is.null(variables$offset)) { + glm_fit <- stats::glm( + formula = formula, + data = .df_row, + family = stats::quasipoisson(link = "log") + ) + } else { + offset <- .df_row[[variables$offset]] + glm_fit <- stats::glm( + formula = formula, + offset = offset, + data = .df_row, + family = stats::quasipoisson(link = "log") + ) + } emmeans_fit <- emmeans::emmeans( glm_fit, specs = arm, @@ -410,7 +439,6 @@ h_glm_negbin <- function(.var, weights) { arm <- variables$arm covariates <- variables$covariates - formula <- stats::as.formula(paste0( .var, " ~ ", " + ", @@ -419,6 +447,26 @@ h_glm_negbin <- function(.var, arm )) + if (is.null(variables$offset)) { + formula <- stats::as.formula(paste0( + .var, " ~ ", + " + ", + paste(covariates, collapse = " + "), + " + ", + arm + )) + } else { + offset <- variables$offset + formula_txt <- sprintf( + "%s ~ %s + %s + offset(%s)", + .var, + arm, paste0(covariates, collapse = " + "), offset + ) + formula <- stats::as.formula( + formula_txt + ) + } + glm_fit <- MASS::glm.nb( formula = formula, data = .df_row, diff --git a/man/summarize_glm_count.Rd b/man/summarize_glm_count.Rd index 5cc315363f..35292c54f3 100644 --- a/man/summarize_glm_count.Rd +++ b/man/summarize_glm_count.Rd @@ -202,6 +202,20 @@ lyt <- basic_table() \%>\% rate = "Rate", rate_ci = "Rate CI", rate_ratio = "Rate Ratio", rate_ratio_ci = "Rate Ratio CI", pval = "p value" ) + ) \%>\% + summarize_glm_count( + vars = "AVAL", + variables = list(arm = "ARM", offset = "lgTMATRSK", covariates = c("REGION1")), + conf_level = 0.95, + distribution = "negbin", + rate_mean_method = "emmeans", + var_labels = "Adjusted (NB) exacerbation rate (per year)", + table_names = "adjNB", + .stats = c("rate", "rate_ci", "rate_ratio", "rate_ratio_ci", "pval"), + .labels = c( + rate = "Rate", rate_ci = "Rate CI", rate_ratio = "Rate Ratio", + rate_ratio_ci = "Rate Ratio CI", pval = "p value" + ) ) build_table(lyt = lyt, df = anl) diff --git a/tests/testthat/_snaps/summarize_glm_count.md b/tests/testthat/_snaps/summarize_glm_count.md index 3aeb76d6f7..d8e25a7906 100644 --- a/tests/testthat/_snaps/summarize_glm_count.md +++ b/tests/testthat/_snaps/summarize_glm_count.md @@ -8,15 +8,15 @@ 2 0.10946932 0.09613709 1.1386793 2.548369e-01 ARMB: Placebo 3 -0.04371457 0.10265030 -0.4258591 6.702105e-01 ARMC: Combination -# h_glm_poisson emmeans-fit works with healthy input +# h_glm_poisson emmeans-fit works with healthy input no offset Code res Output - ARMCD rate std.error df null statistic p.value - 1 ARM A 8.206105 0.5773795 Inf 1 29.91594 1.220818e-196 - 2 ARM B 9.155436 0.5997925 Inf 1 33.80055 1.935734e-250 - 3 ARM C 7.855107 0.5871181 Inf 1 27.57650 2.129731e-167 + ARMCD rate std.error df null statistic p.value + 1 ARM A 2.927536 0.2059807 Inf 1 15.26670 1.274641e-52 + 2 ARM B 3.191781 0.2091005 Inf 1 17.71547 3.185540e-70 + 3 ARM C 3.086207 0.2306739 Inf 1 15.07747 2.278432e-51 # h_glm_poisson glm-fit works with healthy input with covariates @@ -68,22 +68,22 @@ 2 B: Placebo 14.11838 5.392442 Inf 1 6.931571 4.161914e-12 3 C: Combination 10.59153 4.074355 Inf 1 6.135104 8.510352e-10 -# h_glm_negbin glm-fit works with healthy input +# h_glm_negbin glm-fit works with healthy input with offset Code res Output - Estimate SE z_value Pr coefs - 1 1.005041594 0.1992268 5.04471149 4.542062e-07 (Intercept) - 2 0.007741431 0.1919877 0.04032253 9.678360e-01 REGION1Asia - 3 0.317703043 0.2360653 1.34582686 1.783584e-01 REGION1Eurasia - 4 0.591541717 0.4058327 1.45759983 1.449509e-01 REGION1Europe - 5 0.117240049 0.2196300 0.53380718 5.934749e-01 REGION1North America - 6 0.139971334 0.2348685 0.59595610 5.512046e-01 REGION1South America - 7 0.113082781 0.1056295 1.07056107 2.843668e-01 ARMB: Placebo - 8 0.026817451 0.1131811 0.23694292 8.127011e-01 ARMC: Combination - -# h_glm_negbin emmeans-fit works with healthy input + Estimate SE z_value Pr coefs + 1 2.56211826 0.3969418 6.4546439 1.084737e-10 (Intercept) + 2 0.12359121 0.2085554 0.5926060 5.534448e-01 ARMB: Placebo + 3 0.05569230 0.2247874 0.2477554 8.043237e-01 ARMC: Combination + 4 0.05684153 0.3845557 0.1478109 8.824920e-01 REGION1Asia + 5 1.84806287 0.4849801 3.8105953 1.386326e-04 REGION1Eurasia + 6 2.04520468 0.9029032 2.2651428 2.350392e-02 REGION1Europe + 7 0.44720215 0.4417735 1.0122884 3.114002e-01 REGION1North America + 8 1.21153294 0.4690914 2.5827223 9.802419e-03 REGION1South America + +# h_glm_negbin emmeans-fit works with healthy input no offset Code res @@ -189,12 +189,12 @@ [1] 73 $rate - [1] 3.720373 + [1] 37.35687 attr(,"label") [1] "Adjusted Rate" $rate_ci - [1] 3.048181 4.540799 + [1] 24.59065 56.75067 attr(,"label") [1] "95% CI" @@ -257,27 +257,27 @@ [1] 73 $rate - [1] 3.720373 + [1] 37.35687 attr(,"label") [1] "Adjusted Rate" $rate_ci - [1] 3.048181 4.540799 + [1] 24.59065 56.75067 attr(,"label") [1] "95% CI" $rate_ratio - [1] 0.8930767 0.9173508 + [1] 0.8837410 0.9343549 attr(,"label") [1] "Adjusted Rate Ratio" $rate_ratio_ci - [1] 0.7260672 0.7381034 1.0985017 1.1401282 + [1] 0.5872220 0.6062612 1.3299880 1.4400049 attr(,"label") [1] "95% CI" $pval - [1] 0.2843668 0.4367453 + [1] 0.5534448 0.7583367 attr(,"label") [1] "p-value" @@ -322,5 +322,5 @@ 7 8 (10.96%) 2 (2.90%) 0 (0.00%) 10 0 (0.00%) 0 (0.00%) 1 (1.72%) Unadjusted exacerbation rate (per year) - Rate 3.1918 2.9275 3.0862 + Rate 18.6539 21.8760 22.6006 diff --git a/tests/testthat/test-summarize_glm_count.R b/tests/testthat/test-summarize_glm_count.R index 9a7372c640..6135dcbf91 100644 --- a/tests/testthat/test-summarize_glm_count.R +++ b/tests/testthat/test-summarize_glm_count.R @@ -18,7 +18,7 @@ testthat::test_that("h_glm_poisson glm-fit works with healthy input", { testthat::expect_snapshot(res) }) -testthat::test_that("h_glm_poisson emmeans-fit works with healthy input", { +testthat::test_that("h_glm_poisson emmeans-fit works with healthy input no offset", { anl <- tern_ex_adtte %>% filter(PARAMCD == "TNE") anl$AVAL_f <- as.factor(anl$AVAL) @@ -26,7 +26,7 @@ testthat::test_that("h_glm_poisson emmeans-fit works with healthy input", { result <- h_glm_count( .var = "AVAL", .df_row = anl, - variables = list(arm = "ARMCD", offset = "lgTMATRSK", covariates = NULL), + variables = list(arm = "ARMCD", covariates = NULL), distribution = "poisson" ) mat1 <- as.data.frame(broom::tidy(result$emmeans_fit)) @@ -144,7 +144,7 @@ testthat::test_that("h_glm_quasipoisson fails wrong inputs", { ) }) -testthat::test_that("h_glm_negbin glm-fit works with healthy input", { +testthat::test_that("h_glm_negbin glm-fit works with healthy input with offset", { anl <- tern_ex_adtte %>% filter(PARAMCD == "TNE") anl$AVAL_f <- as.factor(anl$AVAL) @@ -164,7 +164,7 @@ testthat::test_that("h_glm_negbin glm-fit works with healthy input", { testthat::expect_snapshot(res) }) -testthat::test_that("h_glm_negbin emmeans-fit works with healthy input", { +testthat::test_that("h_glm_negbin emmeans-fit works with healthy input no offset", { anl <- tern_ex_adtte %>% filter(PARAMCD == "TNE") anl$AVAL_f <- as.factor(anl$AVAL) @@ -172,7 +172,7 @@ testthat::test_that("h_glm_negbin emmeans-fit works with healthy input", { result <- h_glm_negbin( .var = "AVAL", .df_row = anl, - variables = list(arm = "ARM", offset = "lgTMATRSK", covariates = c("REGION1")) + variables = list(arm = "ARM", covariates = c("REGION1")) ) mat1 <- as.data.frame(broom::tidy(result$emmeans_fit))