Title: | Bayesian Evaluation, Analysis, and Simulation Software Tools for Trials |
---|---|
Description: | Bayesian dynamic borrowing with covariate adjustment via inverse probability weighting for simulations and data analyses in clinical trials. This makes it easy to use propensity score methods to balance covariate distributions between external and internal data. |
Authors: | Christina Fillmore [aut, cre] , Ben Arancibia [aut], Nate Bean [aut] , GlaxoSmithKline Research & Development Limited [cph, fnd] |
Maintainer: | Christina Fillmore <[email protected]> |
License: | Apache License (>= 2) |
Version: | 0.0.2 |
Built: | 2024-11-20 10:33:36 UTC |
Source: | https://github.com/gsk-biostatistics/beastt |
Analysis Server
analysisServer(id, reactiveEndpoint)
analysisServer(id, reactiveEndpoint)
id |
mod ID |
reactiveEndpoint |
reactive element with the type of endpoint |
RStudio add-in to create template BDB code
bdb_code_template_maker()
bdb_code_template_maker()
Binary Input UI
binaryanalysisUI(id)
binaryanalysisUI(id)
id |
mod ID |
Binary Server UI
binaryServer(id)
binaryServer(id)
id |
mod it |
Calculate a posterior distribution that is beta (or a mixture of beta components). Only the relevant treatment arms from the internal dataset should be read in (e.g., only the control arm if constructing a posterior distribution for the control response rate).
calc_post_beta(internal_data, response, prior)
calc_post_beta(internal_data, response, prior)
internal_data |
This can either be a propensity score object or a tibble of the internal data. |
response |
Name of response variable |
prior |
A distributional object corresponding to a beta distribution or a mixture distribution of beta components |
For a given arm of an internal trial (e.g., the control arm or an
active treatment arm) of size , suppose the response data are binary
such that
,
. The
posterior distribution for
is written as
where is the likelihood of the
response data from the internal arm and
is a prior
distribution on
(either a beta distribution or a mixture
distribution with an arbitrary number of beta components). The posterior
distribution for
is either a beta distribution or a mixture of
beta components depending on whether the prior is a single beta
distribution or a mixture distribution.
distributional object
library(dplyr) library(distributional) calc_post_beta(internal_data = filter(int_binary_df, trt == 1), response = y, prior = dist_beta(0.5, 0.5))
library(dplyr) library(distributional) calc_post_beta(internal_data = filter(int_binary_df, trt == 1), response = y, prior = dist_beta(0.5, 0.5))
Calculate a posterior distribution that is normal (or a mixture of normal components). Only the relevant treatment arms from the internal dataset should be read in (e.g., only the control arm if constructing a posterior distribution for the control mean).
calc_post_norm(internal_data, response, prior, internal_sd = NULL)
calc_post_norm(internal_data, response, prior, internal_sd = NULL)
internal_data |
This can either be a propensity score object or a tibble of the internal data. |
response |
Name of response variable |
prior |
A distributional object corresponding to a normal distribution, a t distribution, or a mixture distribution of normal and/or t components |
internal_sd |
Standard deviation of internal response data if
assumed known. It can be left as |
For a given arm of an internal trial (e.g., the control arm or an
active treatment arm) of size , suppose the response data are normally
distributed such that
,
.
If
is assumed known, the posterior distribution for
is written as
where is the
likelihood of the response data from the internal arm and
is a prior distribution on
(either a normal distribution, a
distribution, or a mixture distribution with an arbitrary number of
normal and/or
components). Any
components of the prior for
are approximated with a mixture of two normal distributions.
If is unknown, the marginal posterior distribution for
is instead written as
In this case, the prior for is chosen to be
such that
becomes a non-standardized
distribution. This integrated likelihood
is then approximated with a mixture of two normal distributions.
If internal_sd
is supplied a positive value and prior
corresponds to a
single normal distribution, then the posterior distribution for
is a normal distribution. If
internal_sd = NULL
or if other types of prior
distributions are specified (e.g., mixture or t distribution), then the
posterior distribution is a mixture of normal distributions.
distributional object
library(distributional) library(dplyr) post_treated <- calc_post_norm(internal_data = filter(int_norm_df, trt == 1), response = y, prior = dist_normal(50, 10), internal_sd = 0.15)
library(distributional) library(dplyr) post_treated <- calc_post_norm(internal_data = filter(int_norm_df, trt == 1), response = y, prior = dist_normal(50, 10), internal_sd = 0.15)
Calculate a (potentially inverse probability weighted) beta power prior for the control response rate using external control data.
calc_power_prior_beta(external_data, response, prior)
calc_power_prior_beta(external_data, response, prior)
external_data |
This can either be a |
response |
Name of response variable |
prior |
A beta distributional object that is the initial prior for the control response rate before the external control data are observed |
Weighted participant-level response data from an external study are
incorporated into an inverse probability weighted (IPW) power prior for the
control response rate . When borrowing information from an
external control arm of size
, the components of the IPW power
prior for
are defined as follows:
with
weights
:Defining the weights to equal 1 results in a
conventional beta power prior.
Beta power prior object
Other power prior:
calc_power_prior_norm()
library(distributional) library(dplyr) # This function can be used directly on the data calc_power_prior_beta(external_data = ex_binary_df, response = y, prior = dist_beta(0.5, 0.5)) # Or this function can be used with a propensity score object ps_obj <- calc_prop_scr(internal_df = filter(int_binary_df, trt == 0), external_df = ex_binary_df, id_col = subjid, model = ~ cov1 + cov2 + cov3 + cov4) calc_power_prior_beta(ps_obj, response = y, prior = dist_beta(0.5, 0.5))
library(distributional) library(dplyr) # This function can be used directly on the data calc_power_prior_beta(external_data = ex_binary_df, response = y, prior = dist_beta(0.5, 0.5)) # Or this function can be used with a propensity score object ps_obj <- calc_prop_scr(internal_df = filter(int_binary_df, trt == 0), external_df = ex_binary_df, id_col = subjid, model = ~ cov1 + cov2 + cov3 + cov4) calc_power_prior_beta(ps_obj, response = y, prior = dist_beta(0.5, 0.5))
Calculate a (potentially inverse probability weighted) normal power prior using external data.
calc_power_prior_norm( external_data, response, prior = NULL, external_sd = NULL )
calc_power_prior_norm( external_data, response, prior = NULL, external_sd = NULL )
external_data |
This can either be a |
response |
Name of response variable |
prior |
Either |
external_sd |
Standard deviation of external response data if assumed
known. It can be left as |
Weighted participant-level response data from an external study are
incorporated into an inverse probability weighted (IPW) power prior for the
parameter of interest (e.g., the control mean if borrowing
from an external control arm). When borrowing information from an external
dataset of size
, the IPW likelihood of the external response
data
with weights
is defined as
The prior
argument should be either a distributional object with a family
type of normal
or NULL
, corresponding to the use of a normal initial
prior or an improper uniform initial prior (i.e., ), respectively.
The external_sd
argument can be a positive value if the external standard
deviation is assumed known or left as NULL
otherwise. If external_sd = NULL
, then prior
must be NULL
to indicate the use of an improper
uniform initial prior for , and an improper prior is defined
for the unknown external standard deviation such that
. The details of the IPW power prior for each
case are as follows:
external_sd = positive value
(
known):With
either a proper normal or an improper uniform initial prior, the IPW
weighted power prior for is a normal distribution.
external_sd = NULL
(
unknown):With improper
priors for both and
, the marginal IPW weighted
power prior for
after integrating over
is
a non-standardized
distribution.
Defining the weights to equal 1 results in a
conventional normal (or
) power prior if the external standard
deviation is known (unknown).
Normal power prior object
Other power prior:
calc_power_prior_beta()
library(distributional) library(dplyr) # This function can be used directly on the data calc_power_prior_norm(ex_norm_df, response = y, prior = dist_normal(50, 10), external_sd = 0.15) # Or this function can be used with a propensity score object ps_obj <- calc_prop_scr(internal_df = filter(int_norm_df, trt == 0), external_df = ex_norm_df, id_col = subjid, model = ~ cov1 + cov2 + cov3 + cov4) calc_power_prior_norm(ps_obj, response = y, prior = dist_normal(50, 10), external_sd = 0.15)
library(distributional) library(dplyr) # This function can be used directly on the data calc_power_prior_norm(ex_norm_df, response = y, prior = dist_normal(50, 10), external_sd = 0.15) # Or this function can be used with a propensity score object ps_obj <- calc_prop_scr(internal_df = filter(int_norm_df, trt == 0), external_df = ex_norm_df, id_col = subjid, model = ~ cov1 + cov2 + cov3 + cov4) calc_power_prior_norm(ps_obj, response = y, prior = dist_normal(50, 10), external_sd = 0.15)
Calculate the propensity scores and ATT inverse probability weights for participants from internal and external datasets. Only the relevant treatment arms from each dataset should be read in (e.g., only the control arm from each dataset if creating a hybrid control arm).
calc_prop_scr(internal_df, external_df, id_col, model, ...)
calc_prop_scr(internal_df, external_df, id_col, model, ...)
internal_df |
Internal dataset with one row per subject and all the variables needed to run the model |
external_df |
External dataset with one row per subject and all the variables needed to run the model |
id_col |
Name of the column in both datasets used to identify each subject. It must be the same across datasets |
model |
Model used to calculate propensity scores |
... |
Optional arguments |
For the subset of participants in both the external and internal studies for which we want to balance the covariate distributions (e.g., external control and internal control participants if constructing a hybrid control arm), we define a study-inclusion propensity score for each participant as
where denotes a vector of baseline covariates for the
th
participant and
denotes the indicator that the participant is
enrolled in the internal trial (
if internal,
if external). The estimated propensity score
is obtained
using logistic regression.
An ATT inverse probability weight is calculated for each individual as
In a weighted estimator, data from participants in the external study
are given a weight of whereas data
from participants in the internal trial are given a weight of 1.
prop_scr_obj
object, with the internal and the external data and
the propensity score and inverse probability weight calculated for each
subject.
# This can be used for both continuous and binary data library(dplyr) # Continuous calc_prop_scr(internal_df = filter(int_norm_df, trt == 0), external_df = ex_norm_df, id_col = subjid, model = ~ cov1 + cov2 + cov3 + cov4) # Binary calc_prop_scr(internal_df = filter(int_binary_df, trt == 0), external_df = ex_binary_df, id_col = subjid, model = ~ cov1 + cov2 + cov3 + cov4)
# This can be used for both continuous and binary data library(dplyr) # Continuous calc_prop_scr(internal_df = filter(int_norm_df, trt == 0), external_df = ex_norm_df, id_col = subjid, model = ~ cov1 + cov2 + cov3 + cov4) # Binary calc_prop_scr(internal_df = filter(int_binary_df, trt == 0), external_df = ex_binary_df, id_col = subjid, model = ~ cov1 + cov2 + cov3 + cov4)
This is a simulated dataset used to illustrate Bayesian dynamic borrowing in the case when borrowing from an external control arm with a binary endpoint, where the baseline covariate distributions of the internal and external data are balanced via inverse probability weighting.
ex_binary_df
ex_binary_df
ex_binary_df
A data frame with 150 rows and 6 columns:
Unique subject ID
Covariate 1, which is normally distributed around 65 with a SD of 10
Covariate 2, which is binary (0 vs. 1) with about 30% of participants having level 1
Covariate 3, which is binary (0 vs. 1) with about 40% of participants having level 1
Covariate 4, which is binary (0 vs. 1) with about 50% of participants having level 1
Response, which is binary (0 vs. 1)
This is a simulated dataset used to illustrate Bayesian dynamic borrowing in the case when borrowing from an external control arm with a normal endpoint, where the baseline covariate distributions of the internal and external data are balanced via inverse probability weighting.
ex_norm_df
ex_norm_df
ex_norm_df
A data frame with 150 rows and 6 columns:
Unique subject ID
Covariate 1, which is normally distributed around 50 with a SD of 10
Covariate 2, which is binary (0 vs. 1) with about 20% of participants having level 1
Covariate 3, which is binary (0 vs. 1) with about 60% of participants having level 1
Covariate 4, which is binary (0 vs. 1) with about 30% of participants having level 1
Response, which is normally distributed with a SD of 0.15
This is a simulated dataset used to illustrate Bayesian dynamic borrowing in the case when borrowing from an external control arm with a binary endpoint, where the baseline covariate distributions of the internal and external data are balanced via inverse probability weighting.
int_binary_df
int_binary_df
int_binary_df
A data frame with 160 rows and 7 columns:
Unique subject ID
Covariate 1, which is normally distributed around 62 with an sd of 8
Covariate 2, which is binary (0 vs. 1) with about 40% of participants having level 1
Covariate 3, which is binary (0 vs. 1) with about 40% of participants having level 1
Covariate 4, which is binary (0 vs. 1) with about 60% of participants having level 1
Treatment indicator, where 0 = control and 1 = active treatment
Response, which is binary (0 vs. 1)
This is a simulated dataset used to illustrate Bayesian dynamic borrowing in the case when borrowing from an external control arm with a normal endpoint, where the baseline covariate distributions of the internal and external data are balanced via inverse probability weighting.
int_norm_df
int_norm_df
int_norm_df
A data frame with 120 rows and 7 columns:
Unique subject ID
Covariate 1, which is normally distributed around 55 with a SD of 8
Covariate 2, which is binary (0 vs. 1) with about 30% of participants having level 1
Covariate 3, which is binary (0 vs. 1) with about 50% of participants having level 1
Covariate 4, which is binary (0 vs. 1) with about 30% of participants having level 1
Treatment indicator, where 0 = control and 1 = active treatment
Response, which is normally distributed with a SD of 0.15
Test If Propensity Score Object
is_prop_scr(x)
is_prop_scr(x)
x |
Object to test |
Boolean
library(dplyr) x <- calc_prop_scr(internal_df = filter(int_norm_df, trt == 0), external_df = ex_norm_df, id_col = subjid, model = ~ cov1 + cov2 + cov3 + cov4) is_prop_scr(x)
library(dplyr) x <- calc_prop_scr(internal_df = filter(int_norm_df, trt == 0), external_df = ex_norm_df, id_col = subjid, model = ~ cov1 + cov2 + cov3 + cov4) is_prop_scr(x)
norm inputs UI
normalanalysisUI(id)
normalanalysisUI(id)
id |
mod id |
norm input server
normalServer(id)
normalServer(id)
id |
mod id |
Plot Distribution
plot_dist(...)
plot_dist(...)
... |
Distributional object(s) to plot. When passing multiple objects naming them will change the labels in the plot, else they will use the distributional format |
ggplot object that is the density of the provided distribution
library(distributional) plot_dist(dist_normal(0, 1)) #Plotting Multiple plot_dist(dist_normal(0, 1), dist_normal(10, 5)) plot_dist('Prior' = dist_normal(0, 1), 'Posterior' = dist_normal(10, 5))
library(distributional) plot_dist(dist_normal(0, 1)) #Plotting Multiple plot_dist(dist_normal(0, 1), dist_normal(10, 5)) plot_dist('Prior' = dist_normal(0, 1), 'Posterior' = dist_normal(10, 5))
Plot Inputs server
plotServer(id)
plotServer(id)
id |
mod id |
Inputs for plots
plotUI(id, robust)
plotUI(id, robust)
id |
mod id |
robust |
Boolean if the |
Plot overlapping density curves of the propensity scores for both the internal and external participants, or plot external IPWs.
prop_scr_dens( x, variable = c("propensity score", "ps", "inverse probability weight", "ipw"), ... )
prop_scr_dens( x, variable = c("propensity score", "ps", "inverse probability weight", "ipw"), ... )
x |
Propensity score object |
variable |
Variable to plot. It must be either a propensity score ("ps" or "propensity score") or inverse probability weight ("ipw" or "inverse probability weight") |
... |
Optional arguments for |
ggplot object
library(dplyr) ps_obj <- calc_prop_scr(internal_df = filter(int_norm_df, trt == 0), external_df = ex_norm_df, id_col = subjid, model = ~ cov1 + cov2 + cov3 + cov4) # Plotting the Propensity Scores prop_scr_dens(ps_obj) # Or plotting the inverse probability weights prop_scr_dens(ps_obj, variable = "ipw")
library(dplyr) ps_obj <- calc_prop_scr(internal_df = filter(int_norm_df, trt == 0), external_df = ex_norm_df, id_col = subjid, model = ~ cov1 + cov2 + cov3 + cov4) # Plotting the Propensity Scores prop_scr_dens(ps_obj) # Or plotting the inverse probability weights prop_scr_dens(ps_obj, variable = "ipw")
Plot overlapping histograms of the propensity scores for both the internal and external participants, or plot external IPWs.
prop_scr_hist( x, variable = c("propensity score", "ps", "inverse probability weight", "ipw"), ... )
prop_scr_hist( x, variable = c("propensity score", "ps", "inverse probability weight", "ipw"), ... )
x |
Propensity score object |
variable |
Variable to plot. It must be either a propensity score ("ps" or "propensity score") or inverse probability weight ("ipw" or "inverse probability weight") |
... |
Optional arguments for |
ggplot object
library(dplyr) ps_obj <- calc_prop_scr(internal_df = filter(int_norm_df, trt == 0), external_df = ex_norm_df, id_col = subjid, model = ~ cov1 + cov2 + cov3 + cov4) # Plotting the Propensity Scores prop_scr_hist(ps_obj) # Or plotting the inverse probability weights prop_scr_hist(ps_obj, variable = "ipw")
library(dplyr) ps_obj <- calc_prop_scr(internal_df = filter(int_norm_df, trt == 0), external_df = ex_norm_df, id_col = subjid, model = ~ cov1 + cov2 + cov3 + cov4) # Plotting the Propensity Scores prop_scr_hist(ps_obj) # Or plotting the inverse probability weights prop_scr_hist(ps_obj, variable = "ipw")
Plot the unadjusted and IPW-adjusted absolute standardized mean differences for each covariate.
prop_scr_love(x, reference_line = NULL, ...)
prop_scr_love(x, reference_line = NULL, ...)
x |
Propensity score object |
reference_line |
Numeric value of where along the x-axis the vertical reference line should be placed |
... |
Optional options for |
ggplot object
library(dplyr) ps_obj <- calc_prop_scr(internal_df = filter(int_norm_df, trt == 0), external_df = ex_norm_df, id_col = subjid, model = ~ cov1 + cov2 + cov3 + cov4) # Plotting the Propensity Scores prop_scr_love(ps_obj, reference_line = 0.1)
library(dplyr) ps_obj <- calc_prop_scr(internal_df = filter(int_norm_df, trt == 0), external_df = ex_norm_df, id_col = subjid, model = ~ cov1 + cov2 + cov3 + cov4) # Plotting the Propensity Scores prop_scr_love(ps_obj, reference_line = 0.1)
Adds vague normal component, where the level of vagueness is controlled by
the n
parameter
robustify_norm(prior, n, weights = c(0.5, 0.5))
robustify_norm(prior, n, weights = c(0.5, 0.5))
prior |
Normal distributional object |
n |
Number of theoretical participants |
weights |
Vector of weights, where the first number corresponds to the informative component and the second is the vague |
In cases with a normal endpoint, a robust mixture prior can be created by
adding a vague normal component to any normal prior with mean
and variance
.The vague component is calculated to have the
same mean
and variance equal to
, where
n
is the specified number of theoretical participants. If robustifying a normal
power prior that was calculated from external control data and n
is defined as
the number of external control participants, and the vague component would
then correspond to one external control participant's worth of data.
mixture distribution
library(distributional) robustify_norm(dist_normal(0,1), n = 15)
library(distributional) robustify_norm(dist_normal(0,1), n = 15)
Simulation Server
simulationServer(id)
simulationServer(id)
id |
mod ID |
Write Code function
write_code(simulation, endpoint, selections)
write_code(simulation, endpoint, selections)
simulation |
A purpose, either "Simulation" or "Analysis" |
endpoint |
An endpoint type, one of "Binary", "Normal" or "Survival" |
selections |
input from UI |