knitr::opts_chunk$set( collapse = TRUE, comment = "#>" )

library(BayesianMCPMod) library(clinDR) library(dplyr) set.seed(7015)

In this vignette we will show the use of the Bayesian MCPMod package for continuous distributed data. The focus lies on the utilization of an informative prior and the Bayesian MCPMod evaluation of a single trial. We will use data that is included in the clinDR package. More specifically, trial results of BRINTELLIX will be used to illustrate the specification of an informative prior and the usage of such a prior for the Bayesian evaluation of a (hypothetical) new trial. BRINTELLIX is a medication used to treat major depressive disorder. Various clinical trials with different dose groups, including control groups, were conducted.

In a first step, a meta analytic prior will be calculated using historical data from 4 trials with main endpoint Change from baseline in MADRS score after 8 weeks. Please note that only information from the control group will be integrated leading to an informative mixture prior for the control group, while for the active groups a non-informative prior will be specified.

data("metaData") dataset <- filter(as.data.frame(metaData), bname == "BRINTELLIX") histcontrol <- filter( dataset, dose == 0, primtime == 8, indication == "MAJOR DEPRESSIVE DISORDER", protid != 5) hist_data <- data.frame( trial = histcontrol$nctno, est = histcontrol$rslt, se = histcontrol$se, sd = histcontrol$sd, n = histcontrol$sampsize)

Here, we suggest a function to construct a list of prior distributions for the different dose groups. This function is adapted to the needs of this example. Other applications may need a different way to construct prior distributions.

getPriorList <- function ( hist_data, dose_levels, dose_names = NULL, robust_weight = 0.5 ) { sd_tot <- with(hist_data, sum(sd * n) / sum(n)) gmap <- RBesT::gMAP( formula = cbind(est, se) ~ 1 | trial, weights = hist_data$n, data = hist_data, family = gaussian, beta.prior = cbind(0, 100 * sd_tot), tau.dist = "HalfNormal", tau.prior = cbind(0, sd_tot / 4)) prior_ctr <- RBesT::automixfit(gmap) if (!is.null(robust_weight)) { prior_ctr <- suppressMessages(RBesT::robustify( priormix = prior_ctr, weight = robust_weight, sigma = sd_tot)) } prior_trt <- RBesT::mixnorm( comp1 = c(w = 1, m = summary(prior_ctr)[1], n = 1), sigma = sd_tot, param = "mn") prior_list <- c(list(prior_ctr), rep(x = list(prior_trt), times = length(dose_levels[-1]))) if (is.null(dose_names)) { dose_names <- c("Ctr", paste0("DG_", seq_along(dose_levels[-1]))) } names(prior_list) <- dose_names return (prior_list) }

With the dose levels to be investigated, the prior distribution can be constructed.

dose_levels <- c(0, 2.5, 5, 10) prior_list <- getPriorList( hist_data = hist_data, dose_levels = dose_levels, robust_weight = 0.3) getESS(prior_list)

To be able to apply the Bayesian MCPMod approach, candidate models need to be specified using functions from the R package DoseFinding. Since there are only 3 active dose levels we will limit the set of candidate models to a linear, an exponential, and an emax model. Note that the linear candidate model does not require a guesstimate.

exp_guesst <- DoseFinding::guesst( d = 5, p = c(0.2), model = "exponential", Maxd = max(dose_levels)) emax_guesst <- DoseFinding::guesst( d = 2.5, p = c(0.9), model = "emax") mods <- DoseFinding::Mods( linear = NULL, emax = emax_guesst, exponential = exp_guesst, doses = dose_levels, maxEff = -1, placEff = -12.8)

We will use the trial with ct.gov number NCT00735709 as exemplary new trial.

new_trial <- filter( dataset, primtime == 8, indication == "MAJOR DEPRESSIVE DISORDER", protid == 5) n_patients <- c(128, 124, 129, 122)

As outlined in Fleischer et al. [Bayesian MCPMod. Pharmaceutical Statistics. 2022; 21(3): 654-670.], in a first step the posterior is calculated combining the prior information with the estimated results of the new trial. Via the summary function it is possible to print out the summary information of the posterior distributions.

posterior <- getPosterior( prior = prior_list, mu_hat = new_trial$rslt, se_hat = new_trial$se, calc_ess = TRUE) summary(posterior)

For the execution of the testing step of Bayesian MCPMod a critical value on the probability scale will be determined for a given alpha level. This critical value is calculated using the re-estimated contrasts for the frequentist MCPMod to ensure that, when using non-informative priors, the actual error level for falsely declaring a significant trial in the Bayesian MCPMod is controlled by the specified alpha level.

A pseudo-optimal contrast matrix is generated based on the variability of the posterior distribution (see Fleischer et al. 2022 for more details).

crit_pval <- getCritProb( mods = mods, dose_levels = dose_levels, se_new_trial = new_trial$se, alpha_crit_val = 0.05) contr_mat <- getContr( mods = mods, dose_levels = dose_levels, sd_posterior = summary(posterior)[, 2])

Please note that there are different ways to derive the contrasts. The following code shows the implementation of some of these ways but it is not executed and the contrast specification above is used.

# i) the frequentist contrast contr_mat_prior <- getContr( mods = mods, dose_levels = dose_levels, dose_weights = n_patients, prior_list = prior_list) # ii) re-estimated frequentist contrasts contr_mat_prior <- getContr( mods = mods, dose_levels = dose_levels, se_new_trial = new_trial$se) # iii) Bayesian approach using number of patients for new trial and prior distribution contr_mat_prior <- getContr( mods = mods, dose_levels = dose_levels, dose_weights = n_patients, prior_list = prior_list)

The Bayesian MCP testing step is then executed based on the posterior information, the provided contrasts and the multiplicity adjusted critical value.

BMCP_result <- performBayesianMCP( posterior_list = posterior, contr = contr_mat, crit_prob_adj = crit_pval) BMCP_result

The testing step is significant indicating a non-flat dose-response shape. In detail, all 3 models are significant and the p-value for the emax model indicates deviation from the null hypothesis the most.

In the model fitting step the posterior distribution is used as basis. Both simplified and full fitting are performed. For the simplified fit, the multivariate normal distribution of the control group is approximated and reduced by a one-dimensional normal distribution. The actual fit (on this approximated posterior distribution) is then performed using generalized least squares criterion. In contrast, for the full fit, the non-linear optimization problem is addressed via the Nelder Mead algorithm.

The output of the fit includes information about the predicted effects for the included dose levels, the generalized AIC, and the corresponding weights. For the considered case, the simplified and the full fit are very similar.

# Option a) Simplified approach by using approximated posterior distribution fit_simple <- getModelFits( models = names(mods), dose_levels = dose_levels, posterior = posterior, simple = TRUE) # Option b) Making use of the complete posterior distribution fit <- getModelFits( models = names(mods), dose_levels = dose_levels, posterior = posterior, simple = FALSE)

Via the predict() function, one can also receive estimates for dose levels that were not included in the trial.

predict(fit, doses = c(0, 2.5, 4, 5, 7, 10))

It is possible to plot the fitted dose response models and an AIC based average model (black lines).

plot(fit_simple) plot(fit)

To assess the uncertainty, one can additionally visualize credible bands (orange shaded areas, default levels are 50% and 95%). These credible bands are calculated with a bootstrap method as follows: Samples from the posterior distribution are drawn and for every sample the simplified fitting step and a prediction is performed. These predictions are then used to identify and visualize the specified quantiles.

plot(fit, cr_bands = TRUE)

The bootstrap based quantiles can also be directly calculated via the getBootstrapQuantiles() function. For this example, only 6 quantiles are bootstrapped for each model fit.

bs_sample <- getBootstrapSamples( model_fits = fit, doses = c(0, 2.5, 4, 5, 7, 10), n_samples = 6) getBootstrapQuantiles( bs_sample = bs_sample, quantiles = c(0.025, 0.5, 0.975))

Technical note: The median quantile of the bootstrap based procedure is not necessary similar to the main model fit, as they are derived via different procedures. The main fit, i.e. the black lines in the plot, show the best fit of a certain model based on minimizing the residuals for the posterior distribution, while the bootstrap based 50% quantile shows the median fit of the random sampling and fitting procedure.

It is also possible to perform the testing and modeling step in a combined fashion via the performBayesianMCPMod() function. This code serves merely as an example and is not run in this vignette.

performBayesianMCPMod( posterior_list = posterior, contr = contr_mat, crit_prob_adj = crit_pval, simple = FALSE)

**Any scripts or data that you put into this service are public.**

Embedding an R snippet on your website

Add the following code to your website.

For more information on customizing the embed code, read Embedding Snippets.