This vignette demonstrates how to:
Perform multiple imputation using the {rbmi}
package.
Store and modify the imputed data using
{rbmiUtils}
.
Analyze the imputed data using:
CHG
)CRIT1FLN
using
{beeca}
This pattern enables reproducible workflows where imputation and analysis can be separated and revisited independently.
This approach applies Rubin’s Rules for inference after multiple imputation:
We fit a model to each imputed dataset, dervive a response variable on the CHG score, extract marginal effects or other statistics of interest, and combine the results into a single inference using Rubin’s combining rules.
vars <- set_vars(
subjid = "USUBJID",
visit = "AVISIT",
group = "TRT",
outcome = "CHG",
covariates = c("BASE", "STRATA", "REGION")
)
dat <- ADEFF %>%
select(USUBJID, STRATA, REGION, REGIONC, TRT, BASE, CHG, AVISIT)
draws_obj <- draws(data = dat, vars = vars, method = method)
#>
#> SAMPLING FOR MODEL 'rbmi_mmrm' NOW (CHAIN 1).
#> Chain 1:
#> Chain 1: Gradient evaluation took 0.000259 seconds
#> Chain 1: 1000 transitions using 10 leapfrog steps per transition would take 2.59 seconds.
#> Chain 1: Adjust your expectations accordingly!
#> Chain 1:
#> Chain 1:
#> Chain 1: Iteration: 1 / 400 [ 0%] (Warmup)
#> Chain 1: Iteration: 40 / 400 [ 10%] (Warmup)
#> Chain 1: Iteration: 80 / 400 [ 20%] (Warmup)
#> Chain 1: Iteration: 120 / 400 [ 30%] (Warmup)
#> Chain 1: Iteration: 160 / 400 [ 40%] (Warmup)
#> Chain 1: Iteration: 200 / 400 [ 50%] (Warmup)
#> Chain 1: Iteration: 201 / 400 [ 50%] (Sampling)
#> Chain 1: Iteration: 240 / 400 [ 60%] (Sampling)
#> Chain 1: Iteration: 280 / 400 [ 70%] (Sampling)
#> Chain 1: Iteration: 320 / 400 [ 80%] (Sampling)
#> Chain 1: Iteration: 360 / 400 [ 90%] (Sampling)
#> Chain 1: Iteration: 400 / 400 [100%] (Sampling)
#> Chain 1:
#> Chain 1: Elapsed Time: 0.322 seconds (Warm-up)
#> Chain 1: 0.244 seconds (Sampling)
#> Chain 1: 0.566 seconds (Total)
#> Chain 1:
impute_obj <- impute(draws_obj, references = c("Placebo" = "Placebo", "Drug A" = "Placebo"))
ADMI <- get_imputed_data(impute_obj)
pool_obj_ancova <- pool(ana_obj_ancova)
print(pool_obj_ancova)
#>
#> Pool Object
#> -----------
#> Number of Results Combined: 100
#> Method: rubin
#> Confidence Level: 0.95
#> Alternative: two.sided
#>
#> Results:
#>
#> ========================================================
#> parameter est se lci uci pval
#> --------------------------------------------------------
#> trt_Week 24 -2.177 0.182 -2.535 -1.819 <0.001
#> lsm_ref_Week 24 0.077 0.131 -0.18 0.334 0.558
#> lsm_alt_Week 24 -2.1 0.125 -2.347 -1.854 <0.001
#> trt_Week 48 -3.806 0.256 -4.309 -3.304 <0.001
#> lsm_ref_Week 48 0.044 0.185 -0.319 0.408 0.811
#> lsm_alt_Week 48 -3.762 0.176 -4.107 -3.417 <0.001
#> --------------------------------------------------------
tidy_pool_obj(pool_obj_ancova)
#> # A tibble: 6 × 10
#> parameter description visit parameter_type lsm_type est se lci
#> <chr> <chr> <chr> <chr> <chr> <dbl> <dbl> <dbl>
#> 1 trt_Week 24 Treatment … Week… trt <NA> -2.18 0.182 -2.53
#> 2 lsm_ref_Week 24 Least Squa… Week… lsm ref 0.0766 0.131 -0.180
#> 3 lsm_alt_Week 24 Least Squa… Week… lsm alt -2.10 0.125 -2.35
#> 4 trt_Week 48 Treatment … Week… trt <NA> -3.81 0.256 -4.31
#> 5 lsm_ref_Week 48 Least Squa… Week… lsm ref 0.0442 0.185 -0.319
#> 6 lsm_alt_Week 48 Least Squa… Week… lsm alt -3.76 0.176 -4.11
#> # ℹ 2 more variables: uci <dbl>, pval <dbl>
gcomp_responder <- function(data, ...) {
model <- glm(CRIT1FLN ~ TRT + BASE + STRATA + REGION, data = data, family = binomial)
marginal_fit <- get_marginal_effect(
model,
trt = "TRT",
method = "Ge",
type = "HC0",
contrast = "diff",
reference = "Placebo"
)
res <- marginal_fit$marginal_results
list(
trt = list(
est = res[res$STAT == "diff", "STATVAL"][[1]],
se = res[res$STAT == "diff_se", "STATVAL"][[1]],
df = NA
)
)
}
vars_binary <- set_vars(
subjid = "USUBJID",
visit = "AVISIT",
group = "TRT",
outcome = "CRIT1FLN",
covariates = c("BASE", "STRATA", "REGION")
)
ana_obj_prop <- analyse_mi_data(
data = ADMI,
vars = vars_binary,
method = method,
fun = gcomp_responder
)
pool_obj_prop <- pool(ana_obj_prop)
print(pool_obj_prop)
#>
#> Pool Object
#> -----------
#> Number of Results Combined: 100
#> Method: rubin
#> Confidence Level: 0.95
#> Alternative: two.sided
#>
#> Results:
#>
#> ==================================================
#> parameter est se lci uci pval
#> --------------------------------------------------
#> trt -0.063 0.012 -0.087 -0.039 <0.001
#> --------------------------------------------------
ADMI
object can be saved for later reuse.tidy_pool_obj()
is helpful for
reporting and review.