suggested_dependent_pkgs <- c("rstan", "V8") knitr::opts_chunk$set( collapse = TRUE, comment = "#>", eval = all(vapply( suggested_dependent_pkgs, requireNamespace, logical(1), quietly = TRUE ), grepl("gcc", system("R CMD config CC", intern = T))) # had issue when using clang (skip) )
This vignette shows the general purpose and syntax of the tern.rbmi
R package.
The tern.rbmi
provides an interface for Reference Based Multiple Imputation (rbmi
) within the tern framework. For details of the rbmi
package, please see Reference Based Multiple Imputation (rbmi). The basic usage of rbmi
core functions is described
in the quickstart
vignette:
vignette(topic = "quickstart", package = "rbmi")
tern.rbmi
The rbmi
package consists of 4 core functions (plus several helper functions) which are typically called in sequence:
draws()
- fits the imputation models and stores their parametersimpute()
- creates multiple imputed datasetsanalyse()
- analyses each of the multiple imputed datasetspool()
- combines the analysis results across imputed datasets into a single statisticWe use a publicly available example dataset from an antidepressant clinical trial of an active drug versus placebo. The relevant endpoint is the Hamilton 17-item depression rating scale (HAMD17
) which was assessed at baseline and at weeks 1, 2, 4, and 6. Study drug discontinuation occurred in 24% of subjects from the active drug and 26% of subjects from placebo. All data after study drug discontinuation are missing and there is a single additional intermittent missing observation.
library(tern.rbmi) library(dplyr)
data <- antidepressant_data levels(data$THERAPY) <- c("PLACEBO", "DRUG") # This is important! The order defines the computation order later missing_var <- "CHANGE" vars <- list( id = "PATIENT", visit = "VISIT", expand_vars = c("BASVAL", "THERAPY"), group = "THERAPY" ) covariates <- list( draws = c("BASVAL*VISIT", "THERAPY*VISIT"), analyse = c("BASVAL") ) data <- data %>% dplyr::select(PATIENT, THERAPY, VISIT, BASVAL, THERAPY, CHANGE) %>% dplyr::mutate(dplyr::across(.cols = vars$id, ~ as.factor(.x))) %>% dplyr::arrange(dplyr::across(.cols = c(vars$id, vars$visit)))
# Use expand_locf to add rows corresponding to visits with missing outcomes to the dataset data_full <- do.call( expand_locf, args = list( data = data, vars = c(vars$expand_vars, vars$group), group = vars$id, order = c(vars$id, vars$visit) ) %>% append(lapply(data[c(vars$id, vars$visit)], levels)) ) data_full <- data_full %>% dplyr::group_by(dplyr::across(vars$id)) %>% dplyr::mutate(!!vars$group := Filter(Negate(is.na), .data[[vars$group]])[1]) # there are duplicates - use first value data_full <- data_full %>% dplyr::group_by(dplyr::across(c(vars$id, vars$group, vars$visit))) %>% dplyr::slice(1) %>% dplyr::ungroup() # need to have a single ID column data_full <- data_full %>% tidyr::unite("TMP_ID", dplyr::all_of(vars$id), sep = "_#_", remove = FALSE) %>% dplyr::mutate(TMP_ID = as.factor(TMP_ID))
Set the imputation strategy to MAR for each patient with at least one missing observation.
data_ice <- data_full %>% dplyr::arrange(dplyr::across(.cols = c("TMP_ID", vars$visit))) %>% dplyr::filter(is.na(.data[[missing_var]])) %>% dplyr::group_by(TMP_ID) %>% dplyr::slice(1) %>% dplyr::ungroup() %>% dplyr::select(all_of(c("TMP_ID", vars$visit))) %>% dplyr::mutate(strategy = "MAR")
The rbmi::draws()
function fits the imputation models and stores the corresponding parameter estimates or Bayesian posterior parameter draws. The three main inputs to the rbmi::draws()
function are:
Define the names of key variables in our dataset and the covariates included in
the imputation model using rbmi::set_vars()
. Note that the covariates argument
can also include interaction terms.
debug_mode <- FALSE draws_vars <- rbmi::set_vars( outcome = missing_var, visit = vars$visit, group = vars$group, covariates = covariates$draws ) draws_vars$subjid <- "TMP_ID"
Define which imputation method to use, then create samples for the imputation
parameters by running the draws()
function.
draws_method <- rbmi::method_bayes() draws_obj <- rbmi::draws( data = data_full, data_ice = data_ice, vars = draws_vars, method = draws_method )
The next step is to use the parameters from the imputation model to generate the imputed datasets. This is done via the rbmi::impute()
function. The function only has two key inputs: the imputation model output from rbmi::draws()
and the reference groups relevant to reference-based imputation methods. Its usage is thus:
impute_references <- c("DRUG" = "PLACEBO", "PLACEBO" = "PLACEBO") impute_obj <- rbmi::impute( draws_obj, references = impute_references )
The next step is to run the analysis model on each imputed dataset. This is done by defining an analysis function and then calling rbmi::analyse()
to apply this function to each imputed dataset.
# Define analysis model analyse_fun <- ancova ref_levels <- levels(impute_obj$data$group[[1]]) names(ref_levels) <- c("ref", "alt") analyse_obj <- rbmi::analyse( imputations = impute_obj, fun = analyse_fun, vars = rbmi::set_vars( subjid = "TMP_ID", outcome = missing_var, visit = vars$visit, group = vars$group, covariates = covariates$analyse ) )
The rbmi::pool()
function can be used to summarize the analysis results across multiple imputed datasets to provide an overall statistic with a standard error, confidence intervals and a p-value for the hypothesis test of the null hypothesis that the effect is equal to 0.
pool_obj <- rbmi::pool( results = analyse_obj, conf.level = 0.95, alternative = c("two.sided", "less", "greater"), type = c("percentile", "normal") )
Finally create output with rtables
and tern
packages
library(broom) df <- tidy(pool_obj) df
Final product, reshape rbmi
final results to nicely formatted rtable
object.
basic_table() %>% split_cols_by("group", ref_group = levels(df$group)[1]) %>% split_rows_by("visit", split_label = "Visit", label_pos = "topleft") %>% summarize_rbmi() %>% build_table(df)
Any scripts or data that you put into this service are public.
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.