diff --git a/DESCRIPTION b/DESCRIPTION index 0c010575..814a8806 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -1,7 +1,7 @@ Title: Matching Adjusted Indirect Comparison Package: maicplus Version: 0.1.0 -Date: 2023-03-03 +Date: 2024-10-29 Authors@R: c( person( given = "Gregory", @@ -36,9 +36,10 @@ Authors@R: c( person("MSD, Inc.", role = c("cph", "fnd")), person("F. Hoffmann-La Roche AG", role = c("cph", "fnd")) ) -Description: The maicplus package facilitates performing matching adjusted indirect comparison +Description: Facilitates performing matching adjusted indirect comparison (MAIC) analysis where the endpoint of interest is either time-to-event - (e.g. overall survival) or binary (e.g. objective tumor response). + (e.g. overall survival) or binary (e.g. objective tumor response). The method + is described by Signorovitch et al (2012) . License: Apache License 2.0 URL: https://github.com/hta-pharma/maicplus/, https://hta-pharma.github.io/maicplus/ BugReports: https://github.com/hta-pharma/maicplus/issues @@ -75,3 +76,4 @@ Language: en-US LazyData: true Roxygen: list(markdown = TRUE) RoxygenNote: 7.3.2 +Config/testthat/edition: 3 diff --git a/NEWS.md b/NEWS.md index d6a01b00..ce9a6b31 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,13 +1,3 @@ # maicplus 0.1.0 -### New features - -* Add an initializer script. - -### Enhancements - -* Documentation on how to use the initialize a package. - -### Bug fixes - -* None. +- first CRAN release diff --git a/R/binary-helper.R b/R/binary-helper.R index 2475c514..4f5d729d 100644 --- a/R/binary-helper.R +++ b/R/binary-helper.R @@ -91,6 +91,8 @@ get_pseudo_ipd_binary <- function(binary_agd, format = c("stacked", "unstacked") #' @param binobj returned object from \code{stats::glm} #' @param legend label to indicate the binary fit #' @param weighted logical flag indicating whether weights have been applied in the glm fit +#' @returns A `data.frame` containing a summary of the number of events and subjects in a logistic +#' regression model. #' @examples #' data(adrs_sat) #' pseudo_adrs <- get_pseudo_ipd_binary( diff --git a/R/plot_km2.R b/R/plot_km2.R index 2008578a..d0cbcf18 100644 --- a/R/plot_km2.R +++ b/R/plot_km2.R @@ -169,6 +169,7 @@ kmplot2 <- function(weights_object, #' @param use_line_types a numeric vector of length up to 4, line type to the KM curves, #' it will be passed to \code{lty} of \code{lines()} #' @example inst/examples/basic_kmplot2_ex.R +#' @returns A Kaplan-Meier plot object created with `survminer::ggsurvplot()`. #' @export basic_kmplot2 <- function(kmlist, diff --git a/inst/WORDLIST b/inst/WORDLIST index e0da9f60..7c9bde76 100644 --- a/inst/WORDLIST +++ b/inst/WORDLIST @@ -15,6 +15,7 @@ binarize bootswatch Bucher bucher +Chrysostomos Comparator comparator confounders @@ -59,6 +60,7 @@ maicplus medSurv meier MGG +Miranta MSD multivariable navbar diff --git a/inst/examples/maic_unanchored_binary_ex.R b/inst/examples/maic_unanchored_binary_ex.R index 30e4f6d5..4457863b 100644 --- a/inst/examples/maic_unanchored_binary_ex.R +++ b/inst/examples/maic_unanchored_binary_ex.R @@ -1,4 +1,7 @@ +# # unanchored example using maic_unanchored for binary outcome +# + data(centered_ipd_sat) data(adrs_sat) @@ -7,7 +10,7 @@ centered_colnames <- grep("_CENTERED$", colnames(centered_ipd_sat), value = TRUE weighted_data <- estimate_weights(data = centered_ipd_sat, centered_colnames = centered_colnames) weighted_data2 <- estimate_weights( data = centered_ipd_sat, centered_colnames = centered_colnames, - n_boot_iteration = 500 + n_boot_iteration = 100 ) # get dummy binary IPD @@ -51,3 +54,5 @@ maic_unanchored( # binary specific args binary_robust_cov_type = "HC3" ) + +#--------------------------------- diff --git a/inst/examples/maic_unanchored_ex.R b/inst/examples/maic_unanchored_ex.R index c07e23d7..c7740428 100644 --- a/inst/examples/maic_unanchored_ex.R +++ b/inst/examples/maic_unanchored_ex.R @@ -1,4 +1,6 @@ +# # unanchored example using maic_unanchored for time-to-event data +# data(centered_ipd_sat) data(adtte_sat) data(pseudo_ipd_sat) @@ -16,7 +18,7 @@ weighted_data2 <- estimate_weights( centered_colnames = grep("_CENTERED$", names(centered_ipd_sat)), start_val = 0, method = "BFGS", - n_boot_iteration = 500, + n_boot_iteration = 100, set_seed_boot = 1234 ) diff --git a/man/basic_kmplot2.Rd b/man/basic_kmplot2.Rd index 192c8d5c..7d42148b 100644 --- a/man/basic_kmplot2.Rd +++ b/man/basic_kmplot2.Rd @@ -44,6 +44,9 @@ it will be passed to 'col' of \code{lines()}} \item{use_line_types}{a numeric vector of length up to 4, line type to the KM curves, it will be passed to \code{lty} of \code{lines()}} } +\value{ +A Kaplan-Meier plot object created with \code{survminer::ggsurvplot()}. +} \description{ This function generates a basic KM plot using ggplot. } diff --git a/man/glm_makeup.Rd b/man/glm_makeup.Rd index c7ae0c5a..8d7e2a8b 100644 --- a/man/glm_makeup.Rd +++ b/man/glm_makeup.Rd @@ -13,6 +13,10 @@ glm_makeup(binobj, legend = "before matching", weighted = FALSE) \item{weighted}{logical flag indicating whether weights have been applied in the glm fit} } +\value{ +A \code{data.frame} containing a summary of the number of events and subjects in a logistic +regression model. +} \description{ Helper function to summarize outputs from glm fit } diff --git a/man/maic_unanchored.Rd b/man/maic_unanchored.Rd index 65f26357..99180d66 100644 --- a/man/maic_unanchored.Rd +++ b/man/maic_unanchored.Rd @@ -78,7 +78,9 @@ columns. This function is not sensitive to upper or lower case of letters in col } } \examples{ +# # unanchored example using maic_unanchored for time-to-event data +# data(centered_ipd_sat) data(adtte_sat) data(pseudo_ipd_sat) @@ -96,7 +98,7 @@ weighted_data2 <- estimate_weights( centered_colnames = grep("_CENTERED$", names(centered_ipd_sat)), start_val = 0, method = "BFGS", - n_boot_iteration = 500, + n_boot_iteration = 100, set_seed_boot = 1234 ) @@ -134,7 +136,10 @@ result_boot <- maic_unanchored( ) result$descriptive$summary result$inferential$summary +# # unanchored example using maic_unanchored for binary outcome +# + data(centered_ipd_sat) data(adrs_sat) @@ -143,7 +148,7 @@ centered_colnames <- grep("_CENTERED$", colnames(centered_ipd_sat), value = TRUE weighted_data <- estimate_weights(data = centered_ipd_sat, centered_colnames = centered_colnames) weighted_data2 <- estimate_weights( data = centered_ipd_sat, centered_colnames = centered_colnames, - n_boot_iteration = 500 + n_boot_iteration = 100 ) # get dummy binary IPD @@ -187,4 +192,6 @@ maic_unanchored( # binary specific args binary_robust_cov_type = "HC3" ) + +#--------------------------------- } diff --git a/man/maicplus-package.Rd b/man/maicplus-package.Rd index ad0e3653..ecd36ef7 100644 --- a/man/maicplus-package.Rd +++ b/man/maicplus-package.Rd @@ -8,7 +8,7 @@ \description{ \if{html}{\figure{logo.png}{options: style='float: right' alt='logo' width='120'}} -The maicplus package facilitates performing matching adjusted indirect comparison (MAIC) analysis where the endpoint of interest is either time-to-event (e.g. overall survival) or binary (e.g. objective tumor response). +Facilitates performing matching adjusted indirect comparison (MAIC) analysis where the endpoint of interest is either time-to-event (e.g. overall survival) or binary (e.g. objective tumor response). The method is described by Signorovitch et al (2012) \doi{10.1016/j.jval.2012.05.004}. } \seealso{ Useful links: diff --git a/tests/testthat/_snaps/maic_anchored.md b/tests/testthat/_snaps/maic_anchored.md new file mode 100644 index 00000000..758f5a90 --- /dev/null +++ b/tests/testthat/_snaps/maic_anchored.md @@ -0,0 +1,720 @@ +# maic_anchored works for TTE + + Code + testout$descriptive$summary + Output + trt_ind treatment type records n.max n.start events + 1 C C IPD, before matching 500 500.0000 500.0000 500.00000 + 2 A A IPD, before matching 500 500.0000 500.0000 190.00000 + 3 C C IPD, after matching 500 173.3137 173.3137 173.31374 + 4 A A IPD, after matching 500 173.3137 173.3137 55.37398 + 5 C C AgD, external 500 500.0000 500.0000 500.00000 + 6 B B AgD, external 300 300.0000 300.0000 178.00000 + events% rmean se(rmean) median 0.95LCL 0.95UCL + 1 100.00000 2.564797 0.11366994 1.836467 1.644765 2.045808 + 2 38.00000 8.709690 0.35514766 7.587627 6.278691 10.288538 + 3 100.00000 2.679473 0.20670827 1.815795 1.457222 2.292484 + 4 31.95014 10.584609 0.57397937 12.166430 10.244293 NA + 5 100.00000 2.455272 0.09848888 1.851987 1.670540 2.009650 + 6 59.33333 4.303551 0.33672602 2.746131 2.261125 3.320857 + +--- + + Code + testout$inferential$summary + Output + case HR LCL UCL pval + 1 AC 0.2216588 0.1867151 0.2631423 2.136650e-66 + 2 adjusted_AC 0.1631852 0.1113815 0.2390829 1.361531e-20 + 3 BC 0.5718004 0.4811989 0.6794607 2.143660e-10 + 4 AB 0.3876507 0.3039348 0.4944253 2.270430e-14 + 5 adjusted_AB 0.2853885 0.1876867 0.4339497 4.509575e-09 + +--- + + Code + testout$inferential$fit + Output + $km_before_ipd + Call: survfit(formula = Surv(TIME, EVENT) ~ ARM, data = ipd, conf.type = km_conf_type) + + n events median 0.95LCL 0.95UCL + ARM=C 500 500 55.9 50.1 62.3 + ARM=A 500 190 230.9 191.1 313.2 + + $km_after_ipd + Call: survfit(formula = Surv(TIME, EVENT) ~ ARM, data = ipd, weights = ipd$weights, + conf.type = km_conf_type) + + records n events median 0.95LCL 0.95UCL + ARM=C 500 173 173.3 55.3 44.4 69.8 + ARM=A 500 173 55.4 370.3 311.8 NA + + $km_agd + Call: survfit(formula = Surv(TIME, EVENT) ~ ARM, data = pseudo_ipd, + conf.type = km_conf_type) + + n events median 0.95LCL 0.95UCL + ARM=C 500 500 56.4 50.8 61.2 + ARM=B 300 178 83.6 68.8 101.1 + + $model_before_ipd + Call: + coxph(formula = Surv(TIME, EVENT) ~ ARM, data = ipd) + + coef exp(coef) se(coef) z p + ARMA -1.50662 0.22166 0.08753 -17.21 <2e-16 + + Likelihood ratio test=341.2 on 1 df, p=< 2.2e-16 + n= 1000, number of events= 690 + + $model_after_ipd + Call: + coxph(formula = Surv(TIME, EVENT) ~ ARM, data = ipd, weights = weights, + robust = TRUE) + + coef exp(coef) se(coef) robust se z p + ARMA -1.8129 0.1632 0.1602 0.1949 -9.303 <2e-16 + + Likelihood ratio test=155.2 on 1 df, p=< 2.2e-16 + n= 1000, number of events= 690 + + $model_agd + Call: + coxph(formula = Surv(TIME, EVENT) ~ ARM, data = pseudo_ipd) + + coef exp(coef) se(coef) z p + ARMB -0.55897 0.57180 0.08802 -6.351 2.14e-10 + + Likelihood ratio test=43.66 on 1 df, p=3.91e-11 + n= 800, number of events= 678 + + $res_AC + $res_AC$est + [1] 0.1631852 + + $res_AC$se + [1] 0.194863 + + $res_AC$ci_l + [1] 0.1113815 + + $res_AC$ci_u + [1] 0.2390829 + + $res_AC$pval + [1] 1.361531e-20 + + + $res_AC_unadj + $res_AC_unadj$est + [1] 0.2216588 + + $res_AC_unadj$se + [1] 0.08752989 + + $res_AC_unadj$ci_l + [1] 0.1867151 + + $res_AC_unadj$ci_u + [1] 0.2631423 + + $res_AC_unadj$pval + [1] 2.13665e-66 + + + $res_BC + $res_BC$est + [1] 0.5718004 + + $res_BC$se + [1] 0.0880166 + + $res_BC$ci_l + [1] 0.4811989 + + $res_BC$ci_u + [1] 0.6794607 + + $res_BC$pval + [1] 2.14366e-10 + + + $res_AB + result pvalue + "0.29[0.19; 0.43]" "<0.001" + + $res_AB_unadj + result pvalue + "0.39[0.30; 0.49]" "<0.001" + + $boot_res + NULL + + $boot_res_AC + NULL + + $boot_res_AB_mc + NULL + + $boot_res_AB + NULL + + +--- + + Code + testout2$descriptive$summary + Output + trt_ind treatment type records n.max n.start events + 1 C C IPD, before matching 500 500.0000 500.0000 500.00000 + 2 A A IPD, before matching 500 500.0000 500.0000 190.00000 + 3 C C IPD, after matching 500 173.3137 173.3137 173.31374 + 4 A A IPD, after matching 500 173.3137 173.3137 55.37398 + 5 C C AgD, external 500 500.0000 500.0000 500.00000 + 6 B B AgD, external 300 300.0000 300.0000 178.00000 + events% rmean se(rmean) median 0.95LCL 0.95UCL + 1 100.00000 2.564797 0.11366994 1.836467 1.644765 2.045808 + 2 38.00000 8.709690 0.35514766 7.587627 6.278691 10.288538 + 3 100.00000 2.679473 0.20670827 1.815795 1.457222 2.292484 + 4 31.95014 10.584609 0.57397937 12.166430 10.244293 NA + 5 100.00000 2.455272 0.09848888 1.851987 1.670540 2.009650 + 6 59.33333 4.303551 0.33672602 2.746131 2.261125 3.320857 + +--- + + Code + testout2$inferential$summary + Output + case HR LCL UCL pval + 1 AC 0.2216588 0.1867151 0.2631423 2.136650e-66 + 2 adjusted_AC 0.1631852 0.1113815 0.2390829 1.361531e-20 + 3 BC 0.5718004 0.4811989 0.6794607 2.143660e-10 + 4 AB 0.3876507 0.3039348 0.4944253 2.270430e-14 + 5 adjusted_AB 0.2853885 0.1876867 0.4339497 4.509575e-09 + +--- + + Code + testout2$inferential$fit + Output + $km_before_ipd + Call: survfit(formula = Surv(TIME, EVENT) ~ ARM, data = ipd, conf.type = km_conf_type) + + n events median 0.95LCL 0.95UCL + ARM=C 500 500 55.9 50.1 62.3 + ARM=A 500 190 230.9 191.1 313.2 + + $km_after_ipd + Call: survfit(formula = Surv(TIME, EVENT) ~ ARM, data = ipd, weights = ipd$weights, + conf.type = km_conf_type) + + records n events median 0.95LCL 0.95UCL + ARM=C 500 173 173.3 55.3 44.4 69.8 + ARM=A 500 173 55.4 370.3 311.8 NA + + $km_agd + Call: survfit(formula = Surv(TIME, EVENT) ~ ARM, data = pseudo_ipd, + conf.type = km_conf_type) + + n events median 0.95LCL 0.95UCL + ARM=C 500 500 56.4 50.8 61.2 + ARM=B 300 178 83.6 68.8 101.1 + + $model_before_ipd + Call: + coxph(formula = Surv(TIME, EVENT) ~ ARM, data = ipd) + + coef exp(coef) se(coef) z p + ARMA -1.50662 0.22166 0.08753 -17.21 <2e-16 + + Likelihood ratio test=341.2 on 1 df, p=< 2.2e-16 + n= 1000, number of events= 690 + + $model_after_ipd + Call: + coxph(formula = Surv(TIME, EVENT) ~ ARM, data = ipd, weights = weights, + robust = TRUE) + + coef exp(coef) se(coef) robust se z p + ARMA -1.8129 0.1632 0.1602 0.1949 -9.303 <2e-16 + + Likelihood ratio test=155.2 on 1 df, p=< 2.2e-16 + n= 1000, number of events= 690 + + $model_agd + Call: + coxph(formula = Surv(TIME, EVENT) ~ ARM, data = pseudo_ipd) + + coef exp(coef) se(coef) z p + ARMB -0.55897 0.57180 0.08802 -6.351 2.14e-10 + + Likelihood ratio test=43.66 on 1 df, p=3.91e-11 + n= 800, number of events= 678 + + $res_AC + $res_AC$est + [1] 0.1631852 + + $res_AC$se + [1] 0.194863 + + $res_AC$ci_l + [1] 0.1113815 + + $res_AC$ci_u + [1] 0.2390829 + + $res_AC$pval + [1] 1.361531e-20 + + + $res_AC_unadj + $res_AC_unadj$est + [1] 0.2216588 + + $res_AC_unadj$se + [1] 0.08752989 + + $res_AC_unadj$ci_l + [1] 0.1867151 + + $res_AC_unadj$ci_u + [1] 0.2631423 + + $res_AC_unadj$pval + [1] 2.13665e-66 + + + $res_BC + $res_BC$est + [1] 0.5718004 + + $res_BC$se + [1] 0.0880166 + + $res_BC$ci_l + [1] 0.4811989 + + $res_BC$ci_u + [1] 0.6794607 + + $res_BC$pval + [1] 2.14366e-10 + + + $res_AB + result pvalue + "0.29[0.19; 0.43]" "<0.001" + + $res_AB_unadj + result pvalue + "0.39[0.30; 0.49]" "<0.001" + + $boot_res + + STRATIFIED BOOTSTRAP + + + Call: + boot(data = boot_ipd, statistic = stat_fun, R = R, strata = weights_object$boot_strata, + w_obj = weights_object, normalize = normalize_weights) + + + Bootstrap Statistics : + original bias std. error + t1* -1.24586465 -0.161716794 0.28787014 + t2* 0.04571853 0.001994459 0.01042480 + t3* 0.21381891 0.003564636 0.02391077 + t4* -1.81286926 -0.166912210 0.25058383 + t5* 0.19486304 0.003675676 0.02618306 + t6* 0.03797160 0.001994459 0.01042480 + + $boot_res_AC + $boot_res_AC$est + [1] 0.1631852 + + $boot_res_AC$se + [1] NA + + $boot_res_AC$ci_l + [1] 0.1179974 + + $boot_res_AC$ci_u + [1] 0.3151137 + + $boot_res_AC$pval + [1] NA + + + $boot_res_AB_mc + $boot_res_AB_mc$est + [1] 0.287692 + + $boot_res_AB_mc$se + [1] NA + + $boot_res_AB_mc$ci_l + [1] 0.1923646 + + $boot_res_AB_mc$ci_u + [1] 0.5945605 + + $boot_res_AB_mc$pval + [1] NA + + + $boot_res_AB + $boot_res_AB$est + [1] 0.2853885 + + $boot_res_AB$se + [1] NA + + $boot_res_AB$ci_l + [1] 0.1695758 + + $boot_res_AB$ci_u + [1] 0.4802958 + + $boot_res_AB$pval + [1] NA + + + +# maic_anchored for binary case gives the expected result + + Code + testout$descriptive$summary + Output + trt_ind treatment type n events events_pct + 1 C C IPD, before matching 500 338.0000 67.60000 + 2 A A IPD, before matching 500 390.0000 78.00000 + 3 C C IPD, after matching 500 131.2892 26.25784 + 4 A A IPD, after matching 500 142.8968 28.57935 + 5 C C AgD, external 320 120.0000 37.50000 + 6 B B AgD, external 480 280.0000 58.33333 + +--- + + Code + testout$inferential$summary + Output + case OR LCL UCL pval + 1 AC 1.3119021 0.8210000 2.0963303 2.562849e-01 + 2 adjusted_AC 1.6993007 1.2809976 2.2541985 2.354448e-04 + 3 BC 2.3333333 1.7458092 3.1185794 1.035032e-08 + 4 AB 0.5622438 0.3239933 0.9756933 4.061296e-02 + 5 adjusted_AB 0.7282717 0.4857575 1.0918611 1.248769e-01 + +--- + + Code + testout$inferential$fit + Output + $model_before_ipd + + Call: glm(formula = RESPONSE ~ ARM, family = glm_link, data = ipd) + + Coefficients: + (Intercept) ARMA + 0.7354 0.5302 + + Degrees of Freedom: 999 Total (i.e. Null); 998 Residual + Null Deviance: 1170 + Residual Deviance: 1157 AIC: 1161 + + $model_after_ipd + + Call: glm(formula = RESPONSE ~ ARM, family = glm_link, data = ipd, + weights = weights) + + Coefficients: + (Intercept) ARMA + 0.6559 0.2715 + + Degrees of Freedom: 999 Total (i.e. Null); 998 Residual + Null Deviance: 495.5 + Residual Deviance: 493.9 AIC: 454.5 + + $model_agd + + Call: glm(formula = RESPONSE ~ ARM, family = glm_link, data = pseudo_ipd) + + Coefficients: + (Intercept) ARMB + -0.5108 0.8473 + + Degrees of Freedom: 799 Total (i.e. Null); 798 Residual + Null Deviance: 1109 + Residual Deviance: 1075 AIC: 1079 + + $res_AC + $res_AC$est + [1] 1.311902 + + $res_AC$se + [1] 0.3275028 + + $res_AC$ci_l + [1] 0.821 + + $res_AC$ci_u + [1] 2.09633 + + $res_AC$pval + [1] 0.2562849 + + + $res_AC_unadj + $res_AC_unadj$est + [1] 1.699301 + + $res_AC_unadj$se + [1] 0.2488482 + + $res_AC_unadj$ci_l + [1] 1.280998 + + $res_AC_unadj$ci_u + [1] 2.254199 + + $res_AC_unadj$pval + [1] 0.0002354448 + + + $res_BC + $res_BC$est + [1] 2.333333 + + $res_BC$se + [1] 0.3510631 + + $res_BC$ci_l + [1] 1.745809 + + $res_BC$ci_u + [1] 3.118579 + + $res_BC$pval + [1] 1.035032e-08 + + + $res_AB + result pvalue + "0.56[0.32; 0.98]" "0.041" + + $res_AB_unadj + result pvalue + "0.73[0.49; 1.09]" "0.125" + + $boot_res + NULL + + $boot_res_AC + NULL + + $boot_res_AB_mc + NULL + + $boot_res_AB + NULL + + +--- + + Code + testout2$descriptive$summary + Output + trt_ind treatment type n events events_pct + 1 C C IPD, before matching 500 338.0000 67.60000 + 2 A A IPD, before matching 500 390.0000 78.00000 + 3 C C IPD, after matching 500 131.2892 26.25784 + 4 A A IPD, after matching 500 142.8968 28.57935 + 5 C C AgD, external 320 120.0000 37.50000 + 6 B B AgD, external 480 280.0000 58.33333 + +--- + + Code + testout2$inferential$summary + Output + case OR LCL UCL pval + 1 AC 1.3119021 0.8210000 2.0963303 2.562849e-01 + 2 adjusted_AC 1.6993007 1.2809976 2.2541985 2.354448e-04 + 3 BC 2.3333333 1.7458092 3.1185794 1.035032e-08 + 4 AB 0.5622438 0.3239933 0.9756933 4.061296e-02 + 5 adjusted_AB 0.7282717 0.4857575 1.0918611 1.248769e-01 + +--- + + Code + testout2$inferential$fit + Output + $model_before_ipd + + Call: glm(formula = RESPONSE ~ ARM, family = glm_link, data = ipd) + + Coefficients: + (Intercept) ARMA + 0.7354 0.5302 + + Degrees of Freedom: 999 Total (i.e. Null); 998 Residual + Null Deviance: 1170 + Residual Deviance: 1157 AIC: 1161 + + $model_after_ipd + + Call: glm(formula = RESPONSE ~ ARM, family = glm_link, data = ipd, + weights = weights) + + Coefficients: + (Intercept) ARMA + 0.6559 0.2715 + + Degrees of Freedom: 999 Total (i.e. Null); 998 Residual + Null Deviance: 495.5 + Residual Deviance: 493.9 AIC: 454.5 + + $model_agd + + Call: glm(formula = RESPONSE ~ ARM, family = glm_link, data = pseudo_ipd) + + Coefficients: + (Intercept) ARMB + -0.5108 0.8473 + + Degrees of Freedom: 799 Total (i.e. Null); 798 Residual + Null Deviance: 1109 + Residual Deviance: 1075 AIC: 1079 + + $res_AC + $res_AC$est + [1] 1.311902 + + $res_AC$se + [1] 0.3275028 + + $res_AC$ci_l + [1] 0.821 + + $res_AC$ci_u + [1] 2.09633 + + $res_AC$pval + [1] 0.2562849 + + + $res_AC_unadj + $res_AC_unadj$est + [1] 1.699301 + + $res_AC_unadj$se + [1] 0.2488482 + + $res_AC_unadj$ci_l + [1] 1.280998 + + $res_AC_unadj$ci_u + [1] 2.254199 + + $res_AC_unadj$pval + [1] 0.0002354448 + + + $res_BC + $res_BC$est + [1] 2.333333 + + $res_BC$se + [1] 0.3510631 + + $res_BC$ci_l + [1] 1.745809 + + $res_BC$ci_u + [1] 3.118579 + + $res_BC$pval + [1] 1.035032e-08 + + + $res_AB + result pvalue + "0.56[0.32; 0.98]" "0.041" + + $res_AB_unadj + result pvalue + "0.73[0.49; 1.09]" "0.125" + + $boot_res + + STRATIFIED BOOTSTRAP + + + Call: + boot(data = boot_ipd, statistic = stat_fun, R = R, strata = weights_object$boot_strata, + w_obj = weights_object, eff_measure = eff_measure, normalize = normalize_weights) + + + Bootstrap Statistics : + original bias std. error + t1* -0.69289322 0.59931037 0.259160031 + t2* 0.06888563 0.01114340 0.004040355 + t3* 0.26246071 0.02034770 0.007139486 + t4* 0.27147808 0.45352064 0.291583054 + t5* 0.21675070 0.02420063 0.008380500 + t6* 0.04698086 0.01114340 0.004040355 + + $boot_res_AC + $boot_res_AC$est + [1] 1.311902 + + $boot_res_AC$se + [1] NA + + $boot_res_AC$ci_l + [1] 0.4706998 + + $boot_res_AC$ci_u + [1] 1.476168 + + $boot_res_AC$pval + [1] NA + + + $boot_res_AB_mc + $boot_res_AB_mc$est + [1] 0.500127 + + $boot_res_AB_mc$se + [1] NA + + $boot_res_AB_mc$ci_l + [1] 0.1652744 + + $boot_res_AB_mc$ci_u + [1] 0.4564577 + + $boot_res_AB_mc$pval + [1] NA + + + $boot_res_AB + $boot_res_AB$est + [1] 0.5622438 + + $boot_res_AB$se + [1] NA + + $boot_res_AB$ci_l + [1] 0.2962009 + + $boot_res_AB$ci_u + [1] 1.067242 + + $boot_res_AB$pval + [1] NA + + + diff --git a/tests/testthat/_snaps/maic_unanchored.md b/tests/testthat/_snaps/maic_unanchored.md new file mode 100644 index 00000000..2dcbc7b5 --- /dev/null +++ b/tests/testthat/_snaps/maic_unanchored.md @@ -0,0 +1,450 @@ +# test binary case + + Code + testout$descriptive$summary + Output + trt_ind treatment type n events events_pct + 1 B B Before matching 400 280.0000 70.00000 + 2 A A Before matching 500 390.0000 78.00000 + 3 B B After matching 400 280.0000 70.00000 + 4 A A After matching 500 142.8968 28.57935 + +--- + + Code + testout$inferential$summary + Output + case RR LCL UCL pval + 1 AB 1.114286 0.9557015 1.299185 0.1671206 + 2 adjusted_AB 1.023627 0.9123647 1.148457 0.6908096 + +--- + + Code + testout$inferential$fit + Output + $model_before + + Call: glm(formula = RESPONSE ~ ARM, family = glm_link, data = dat) + + Coefficients: + (Intercept) ARMA + -0.3567 0.1082 + + Degrees of Freedom: 899 Total (i.e. Null); 898 Residual + Null Deviance: 395.5 + Residual Deviance: 393.5 AIC: 1738 + + $model_after + + Call: glm(formula = RESPONSE ~ ARM, family = glm_link, data = dat, + weights = weights) + + Coefficients: + (Intercept) ARMA + -0.35667 0.02335 + + Degrees of Freedom: 899 Total (i.e. Null); 898 Residual + Null Deviance: 295.1 + Residual Deviance: 295 AIC: 1145 + + $res_AB + $res_AB$est + [1] 1.023627 + + $res_AB$se + [1] 0.06025155 + + $res_AB$ci_l + [1] 0.9123647 + + $res_AB$ci_u + [1] 1.148457 + + $res_AB$pval + [1] 0.6908096 + + + $res_AB_unadj + $res_AB_unadj$est + [1] 1.114286 + + $res_AB_unadj$se + [1] 0.08768422 + + $res_AB_unadj$ci_l + [1] 0.9557015 + + $res_AB_unadj$ci_u + [1] 1.299185 + + $res_AB_unadj$pval + [1] 0.1671206 + + + $boot_res + NULL + + $boot_res_AB + NULL + + +--- + + Code + testout2$descriptive + Output + $summary + trt_ind treatment type n events events_pct + 1 B B Before matching 400 280.0000 70.00000 + 2 A A Before matching 500 390.0000 78.00000 + 3 B B After matching 400 280.0000 70.00000 + 4 A A After matching 500 142.8968 28.57935 + + +--- + + Code + testout2$inferential$fit + Output + $model_before + + Call: glm(formula = RESPONSE ~ ARM, family = glm_link, data = dat) + + Coefficients: + (Intercept) ARMA + -0.3567 0.1082 + + Degrees of Freedom: 899 Total (i.e. Null); 898 Residual + Null Deviance: 395.5 + Residual Deviance: 393.5 AIC: 1738 + + $model_after + + Call: glm(formula = RESPONSE ~ ARM, family = glm_link, data = dat, + weights = weights) + + Coefficients: + (Intercept) ARMA + -0.35667 0.02335 + + Degrees of Freedom: 899 Total (i.e. Null); 898 Residual + Null Deviance: 295.1 + Residual Deviance: 295 AIC: 1145 + + $res_AB + $res_AB$est + [1] 1.023627 + + $res_AB$se + [1] 0.06025155 + + $res_AB$ci_l + [1] 0.9123647 + + $res_AB$ci_u + [1] 1.148457 + + $res_AB$pval + [1] 0.6908096 + + + $res_AB_unadj + $res_AB_unadj$est + [1] 1.114286 + + $res_AB_unadj$se + [1] 0.08768422 + + $res_AB_unadj$ci_l + [1] 0.9557015 + + $res_AB_unadj$ci_u + [1] 1.299185 + + $res_AB_unadj$pval + [1] 0.1671206 + + + $boot_res + + STRATIFIED BOOTSTRAP + + + Call: + boot(data = boot_ipd, statistic = stat_fun, R = R, strata = weights_object$boot_strata, + w_obj = weights_object, pseudo_ipd = pseudo_ipd, normalize = normalize_weights) + + + Bootstrap Statistics : + original bias std. error + t1* 0.02335185 1.366708e-02 0.0538052765 + t2* 0.01056949 8.109601e-05 0.0005263733 + + $boot_res_AB + $boot_res_AB$est + [1] 1.023627 + + $boot_res_AB$se + [1] NA + + $boot_res_AB$ci_l + [1] 0.9086715 + + $boot_res_AB$ci_u + [1] 1.122032 + + $boot_res_AB$pval + [1] NA + + + +--- + + Code + testout2$inferential$summary + Output + case RR LCL UCL pval + 1 AB 1.114286 0.9557015 1.299185 0.1671206 + 2 adjusted_AB 1.023627 0.9123647 1.148457 0.6908096 + +# test time to event case + + Code + testout$descriptive$summary + Output + trt_ind treatment type records n.max n.start events + 1 B B Before matching 300 300.0000 300.0000 178.00000 + 2 A A Before matching 500 500.0000 500.0000 190.00000 + 3 B B After matching 300 300.0000 300.0000 178.00000 + 4 A A After matching 500 199.4265 199.4265 65.68878 + rmean se(rmean) median 0.95LCL 0.95UCL + 1 4.303551 0.3367260 2.746131 2.261125 3.320857 + 2 8.709690 0.3551477 7.587627 6.278691 10.288538 + 3 4.303551 0.3367260 2.746131 2.261125 3.320857 + 4 10.166029 0.5499915 11.900015 7.815275 14.873786 + +--- + + Code + testout$inferential$summary + Output + case HR LCL UCL pval + 1 AB 0.3748981 0.3039010 0.4624815 5.245204e-20 + 2 adjusted_AB 0.2834780 0.2074664 0.3873387 2.473442e-15 + +--- + + Code + testout$inferential$fit + Output + $km_before + Call: survfit(formula = Surv(TIME, EVENT) ~ ARM, data = dat, conf.type = km_conf_type) + + n events median 0.95LCL 0.95UCL + ARM=B 300 178 83.6 68.8 101 + ARM=A 500 190 230.9 191.1 313 + + $km_after + Call: survfit(formula = Surv(TIME, EVENT) ~ ARM, data = dat, weights = dat$weights, + conf.type = km_conf_type) + + records n events median 0.95LCL 0.95UCL + ARM=B 300 300 178.0 83.6 68.8 101 + ARM=A 500 199 65.7 362.2 237.9 453 + + $model_before + Call: + coxph(formula = Surv(TIME, EVENT) ~ ARM, data = dat) + + coef exp(coef) se(coef) z p + ARMA -0.9811 0.3749 0.1071 -9.159 <2e-16 + + Likelihood ratio test=80.62 on 1 df, p=< 2.2e-16 + n= 800, number of events= 368 + + $model_after + Call: + coxph(formula = Surv(TIME, EVENT) ~ ARM, data = dat, weights = weights, + robust = TRUE) + + coef exp(coef) se(coef) robust se z p + ARMA -1.2606 0.2835 0.1504 0.1593 -7.915 2.47e-15 + + Likelihood ratio test=80.4 on 1 df, p=< 2.2e-16 + n= 800, number of events= 368 + + $res_AB + $res_AB$est + [1] 0.283478 + + $res_AB$se + [1] 0.04601759 + + $res_AB$ci_l + [1] 0.2074664 + + $res_AB$ci_u + [1] 0.3873387 + + $res_AB$pval + [1] 2.473442e-15 + + + $res_AB_unadj + $res_AB_unadj$est + [1] 0.3748981 + + $res_AB_unadj$se + [1] 0.0405065 + + $res_AB_unadj$ci_l + [1] 0.303901 + + $res_AB_unadj$ci_u + [1] 0.4624815 + + $res_AB_unadj$pval + [1] 5.245204e-20 + + + $boot_res + NULL + + $boot_res_AB + NULL + + +--- + + Code + testout2$descriptive$summary + Output + trt_ind treatment type records n.max n.start events + 1 B B Before matching 300 300.0000 300.0000 178.00000 + 2 A A Before matching 500 500.0000 500.0000 190.00000 + 3 B B After matching 300 300.0000 300.0000 178.00000 + 4 A A After matching 500 199.4265 199.4265 65.68878 + rmean se(rmean) median 0.95LCL 0.95UCL + 1 4.303551 0.3367260 2.746131 2.261125 3.320857 + 2 8.709690 0.3551477 7.587627 6.278691 10.288538 + 3 4.303551 0.3367260 2.746131 2.261125 3.320857 + 4 10.166029 0.5499915 11.900015 7.815275 14.873786 + +--- + + Code + testout2$inferential$summary + Output + case HR LCL UCL pval + 1 AB 0.3748981 0.3039010 0.4624815 5.245204e-20 + 2 adjusted_AB 0.2834780 0.2074664 0.3873387 2.473442e-15 + +--- + + Code + testout2$inferential$fit + Output + $km_before + Call: survfit(formula = Surv(TIME, EVENT) ~ ARM, data = dat, conf.type = km_conf_type) + + n events median 0.95LCL 0.95UCL + ARM=B 300 178 83.6 68.8 101 + ARM=A 500 190 230.9 191.1 313 + + $km_after + Call: survfit(formula = Surv(TIME, EVENT) ~ ARM, data = dat, weights = dat$weights, + conf.type = km_conf_type) + + records n events median 0.95LCL 0.95UCL + ARM=B 300 300 178.0 83.6 68.8 101 + ARM=A 500 199 65.7 362.2 237.9 453 + + $model_before + Call: + coxph(formula = Surv(TIME, EVENT) ~ ARM, data = dat) + + coef exp(coef) se(coef) z p + ARMA -0.9811 0.3749 0.1071 -9.159 <2e-16 + + Likelihood ratio test=80.62 on 1 df, p=< 2.2e-16 + n= 800, number of events= 368 + + $model_after + Call: + coxph(formula = Surv(TIME, EVENT) ~ ARM, data = dat, weights = weights, + robust = TRUE) + + coef exp(coef) se(coef) robust se z p + ARMA -1.2606 0.2835 0.1504 0.1593 -7.915 2.47e-15 + + Likelihood ratio test=80.4 on 1 df, p=< 2.2e-16 + n= 800, number of events= 368 + + $res_AB + $res_AB$est + [1] 0.283478 + + $res_AB$se + [1] 0.04601759 + + $res_AB$ci_l + [1] 0.2074664 + + $res_AB$ci_u + [1] 0.3873387 + + $res_AB$pval + [1] 2.473442e-15 + + + $res_AB_unadj + $res_AB_unadj$est + [1] 0.3748981 + + $res_AB_unadj$se + [1] 0.0405065 + + $res_AB_unadj$ci_l + [1] 0.303901 + + $res_AB_unadj$ci_u + [1] 0.4624815 + + $res_AB_unadj$pval + [1] 5.245204e-20 + + + $boot_res + + STRATIFIED BOOTSTRAP + + + Call: + boot(data = boot_ipd, statistic = stat_fun, R = R, strata = weights_object$boot_strata, + w_obj = weights_object, pseudo_ipd = pseudo_ipd, normalize = normalize_weights) + + + Bootstrap Statistics : + original bias std. error + t1* -1.26062079 0.0024513461 0.131388233 + t2* 0.02536718 0.0005819358 0.002670424 + + $boot_res_AB + $boot_res_AB$est + [1] 0.283478 + + $boot_res_AB$se + [1] NA + + $boot_res_AB$ci_l + [1] 0.2185832 + + $boot_res_AB$ci_u + [1] 0.3658412 + + $boot_res_AB$pval + [1] NA + + + diff --git a/tests/testthat/data/test_binary_anchored_expected.RData b/tests/testthat/data/test_binary_anchored_expected.RData deleted file mode 100644 index 8383a644..00000000 Binary files a/tests/testthat/data/test_binary_anchored_expected.RData and /dev/null differ diff --git a/tests/testthat/data/test_binary_unanchored_expected.RData b/tests/testthat/data/test_binary_unanchored_expected.RData deleted file mode 100644 index 6e775bc5..00000000 Binary files a/tests/testthat/data/test_binary_unanchored_expected.RData and /dev/null differ diff --git a/tests/testthat/data/test_tte_anchored_expected.RData b/tests/testthat/data/test_tte_anchored_expected.RData deleted file mode 100644 index 53f5be06..00000000 Binary files a/tests/testthat/data/test_tte_anchored_expected.RData and /dev/null differ diff --git a/tests/testthat/data/test_tte_unanchored_expected.RData b/tests/testthat/data/test_tte_unanchored_expected.RData deleted file mode 100644 index 5d60074a..00000000 Binary files a/tests/testthat/data/test_tte_unanchored_expected.RData and /dev/null differ diff --git a/tests/testthat/test-maic_anchored.R b/tests/testthat/test-maic_anchored.R index 7a532924..42e3f0d7 100644 --- a/tests/testthat/test-maic_anchored.R +++ b/tests/testthat/test-maic_anchored.R @@ -54,24 +54,15 @@ test_that("maic_anchored works for TTE", { km_conf_type = "log-log" ) - if (FALSE) { - # Manual snapshot of results - expectout <- testout - expectout2 <- testout2 - save(list = c("expectout", "expectout2"), file = test_path("data", "test_tte_anchored_expected.RData")) - } - - load(test_path("data", "test_tte_anchored_expected.RData")) # Compare robust outputs - expect_equal(testout$descriptive, expectout$descriptive) - expect_equal(testout$inferential$summary, expectout$inferential$summary) - expect_equal(testout$inferential$fit$res_AB, expectout$inferential$fit$res_AB) + expect_snapshot(testout$descriptive$summary) + expect_snapshot(testout$inferential$summary) + expect_snapshot(testout$inferential$fit) # Compare bootstrap outputs - expect_equal(testout2$descriptive, expectout2$descriptive) - expect_equal(testout2$inferential$fit$boot_est["t"], expectout2$inferential$fit$boot_est["t"]) - expect_equal(testout2$inferential$fit$boot_est["seed"], expectout2$inferential$fit$boot_est["seed"]) - expect_equal(testout2$inferential$boot_res_AB, expectout2$inferential$boot_res_AB) + expect_snapshot(testout2$descriptive$summary) + expect_snapshot(testout2$inferential$summary) + expect_snapshot(testout2$inferential$fit) }) test_that("maic_anchored for binary case gives the expected result", { @@ -132,24 +123,13 @@ test_that("maic_anchored for binary case gives the expected result", { eff_measure = "OR" ) - if (FALSE) { - # Manual snapshot of results - expectout <- testout - expectout2 <- testout2 - save(list = c("expectout", "expectout2"), file = test_path("data", "test_binary_anchored_expected.RData")) - } - - load(test_path("data", "test_binary_anchored_expected.RData")) - # Compare robust outputs - expect_equal(testout$descriptive, expectout$descriptive) - expect_equal(testout$inferential$summary, expectout$inferential$summary) - expect_equal(testout$inferential$fit$res_AB$est, testout$inferential$fit$res_AB$est) - expect_equal(testout$inferential$fit$res_AB$pvalue, testout$inferential$fit$res_AB$pvalue) + expect_snapshot(testout$descriptive$summary) + expect_snapshot(testout$inferential$summary) + expect_snapshot(testout$inferential$fit) # Compare bootstrap outputs - expect_equal(testout2$descriptive, expectout2$descriptive) - expect_equal(testout2$inferential$fit$boot_est["t"], expectout2$inferential$fit$boot_est["t"]) - expect_equal(testout2$inferential$fit$boot_est["seed"], expectout2$inferential$fit$boot_est["seed"]) - expect_equal(testout2$inferential$boot_res_AB, expectout2$inferential$boot_res_AB) + expect_snapshot(testout2$descriptive$summary) + expect_snapshot(testout2$inferential$summary) + expect_snapshot(testout2$inferential$fit) }) diff --git a/tests/testthat/test-maic_unanchored.R b/tests/testthat/test-maic_unanchored.R index dd2ec810..0035c811 100644 --- a/tests/testthat/test-maic_unanchored.R +++ b/tests/testthat/test-maic_unanchored.R @@ -60,25 +60,16 @@ test_that("test binary case", { binary_robust_cov_type = "HC3" ) - if (FALSE) { - # Manual snapshot of results - expectout <- testout - expectout2 <- testout2 - save(list = c("expectout", "expectout2"), file = test_path("data", "test_binary_unanchored_expected.RData")) - } - - load(test_path("data", "test_binary_unanchored_expected.RData")) # Compare robust outputs - expect_equal(testout$descriptive, expectout$descriptive) - expect_equal(testout$inferential$summary, expectout$inferential$summary) - expect_equal(testout$inferential$fit, expectout$inferential$fit) + expect_snapshot(testout$descriptive$summary) + expect_snapshot(testout$inferential$summary) + expect_snapshot(testout$inferential$fit) # Compare bootstrap outputs - expect_equal(testout2$descriptive, expectout2$descriptive) - expect_equal(testout2$inferential$fit$boot_est["t"], expectout2$inferential$fit$boot_est["t"]) - expect_equal(testout2$inferential$fit$boot_est["seed"], expectout2$inferential$fit$boot_est["seed"]) - expect_equal(testout2$inferential$boot_res_AB, expectout2$inferential$boot_res_AB) + expect_snapshot(testout2$descriptive) + expect_snapshot(testout2$inferential$fit) + expect_snapshot(testout2$inferential$summary) }) @@ -140,22 +131,14 @@ test_that("test time to event case", { km_conf_type = "log-log" ) - if (FALSE) { - # Manual snapshot of results - expectout <- testout - expectout2 <- testout2 - save(list = c("expectout", "expectout2"), file = test_path("data", "test_tte_unanchored_expected.RData")) - } - load(test_path("data", "test_tte_unanchored_expected.RData")) # Compare robust outputs - expect_equal(testout$descriptive, expectout$descriptive) - expect_equal(testout$inferential$summary, expectout$inferential$summary) - expect_equal(testout$inferential$fit$res_AB, expectout$inferential$fit$res_AB) + expect_snapshot(testout$descriptive$summary) + expect_snapshot(testout$inferential$summary) + expect_snapshot(testout$inferential$fit) # Compare bootstrap outputs - expect_equal(testout2$descriptive, expectout2$descriptive) - expect_equal(testout2$inferential$fit$boot_est["t"], expectout2$inferential$fit$boot_est["t"]) - expect_equal(testout2$inferential$fit$boot_est["seed"], expectout2$inferential$fit$boot_est["seed"]) - expect_equal(testout2$inferential$boot_res_AB, expectout2$inferential$boot_res_AB) + expect_snapshot(testout2$descriptive$summary) + expect_snapshot(testout2$inferential$summary) + expect_snapshot(testout2$inferential$fit) }) diff --git a/tests/testthat/test-matching.R b/tests/testthat/test-matching.R index 7aab16b9..1cbdacc1 100644 --- a/tests/testthat/test-matching.R +++ b/tests/testthat/test-matching.R @@ -31,7 +31,7 @@ test_that("optimise_weights works as expected", { result <- optimise_weights(object, par = c(0, 0), trace = 2), "converged" ) - expect_equal(result$alpha, c(-0.07702229, 0.06826333)) + expect_equal(result$alpha, c(-0.0770222925868337, 0.0682633331364419)) expect_equal( result$wt[, 1], c(