The OncoBayes2 package provides flexible functions for Bayesian meta-analytic modeling of the incidence of Dose Limiting Toxicities (DLTs) by dose level, under treatment regimes involving any number of combination partners. Such models may be used to ensure patient safety during trial conduct by supporting dose-escalation decisions. In addition, the model can support estimation of the Maximum Tolerated Dose (MTD) in adaptive Bayesian dose-escalation designs.
Whereas traditional dose escalation designs, such as the 3+3 design, base the dosing decisions on predefined rules about the number of DLTs in the last one or two cohorts at the current dose, model-based designs such as those using Bayesian Logistic Regression Models (BLRMs) endeavor to model the dose-toxicity relationship as a continuous curve, and allow the model to guide dosing decisions. In this way, all available data contributes to the dosing decisions. Furthermore, extensions to the BLRM approach can support inclusion of available historical data on the compound(s) involved.
The package supports incorporation of historical data through a Meta-Analytic-Combined (MAC) framework [1], which stratifies these heterogeneous sources of information through a hierarchical model. Additionally, it allows the use of EXchangeable/Non-EXchangeable (EX/NEX) priors to manage the amount of information-sharing across subgroups of historical and/or concurrent sources of data.
Consider the application described in Section 3.2 of [1], in which the risk of DLT is to be studied as a function of dose for two drugs, drug A and drug B. Historical information on the toxicity profiles of these two drugs is available from single agent trials trial_A and trial_B. The historical data for this example is available in an internal data set.
| group_id | drug_A | drug_B | num_patients | num_toxicities | cohort_time |
|---|---|---|---|---|---|
| trial_A | 3.0 | 0.0 | 3 | 0 | 0 |
| trial_A | 4.5 | 0.0 | 3 | 0 | 0 |
| trial_A | 6.0 | 0.0 | 6 | 0 | 0 |
| trial_A | 8.0 | 0.0 | 3 | 2 | 0 |
| trial_B | 0.0 | 33.3 | 3 | 0 | 0 |
| trial_B | 0.0 | 50.0 | 3 | 0 | 0 |
| trial_B | 0.0 | 100.0 | 4 | 0 | 0 |
| trial_B | 0.0 | 200.0 | 9 | 0 | 0 |
| trial_B | 0.0 | 400.0 | 15 | 0 | 0 |
| trial_B | 0.0 | 800.0 | 20 | 2 | 0 |
| trial_B | 0.0 | 1120.0 | 17 | 4 | 0 |
The objective is to aid dosing and dose-escalation decisions in a future trial, trial_AB, in which the drugs will be combined. Additionally, another investigator-initiated trial IIT will study the same combination concurrently. Note that these as-yet-unobserved sources of data are included in the input data as unobserved factor levels. This mechanism allows us to specify a joint meta-analytic prior for all four sources of historical and concurrent data.
## [1] "trial_A" "trial_B" "IIT" "trial_AB"
The function blrm_trial provides an object-oriented framework for operationalizing the dose-escalation trial design. This framework is intended as a convenient wrapper for the main model-fitting engine of the package, the blrm_exnex() function. The latter allows additional flexibility for specifying the functional form of the model, but blrm_trial covers the most common use-cases. This introductory vignette highlights blrm_trial in lieu of blrm_exnex; the reader is referred to the help-page of the function?blrm_exnex for more details.
One begins with blrm_trial by specifying three key design elements:
Information about the study drugs is encoded through a tibble as below. This includes the names of the study-drugs, the reference doses (see [3] or ?blrm_exnex to understand the role this choice plays in the model specification), the dosing units, and (optionally) the a priori expected DLT rate for each study drug given individually at the respective reference doses.
All design information for the study described in [1] is also included as built-in datasets, which are part of the OncoBayes2 package.
| drug_name | dose_ref | dose_unit | reference_p_dlt |
|---|---|---|---|
| drug_A | 300 | mg | 0.1 |
| drug_B | 960 | mg | 0.1 |
The provisional dose levels are specified as below. For conciseness, we begin by fixing the dose level of drug A in these provisional doses.
| group_id | drug_A | drug_B | dose_id |
|---|---|---|---|
| trial_AB | 3 | 0 | 22 |
| trial_AB | 3 | 400 | 23 |
| trial_AB | 3 | 600 | 24 |
| trial_AB | 3 | 800 | 25 |
blrm_trialTogether with the data described in the previous section, these objects can be used to initialize a blrm_trial object.
combo2_trial_setup <- blrm_trial(
data = hist_combo2,
drug_info = drug_info_combo2,
dose_info = dose_info,
simplified_prior = FALSE
)## No stratum defined - assigning all groups to single stratum "all"
## Please configure blrm_exnex using the update() function.
At this point, the trial design has been initialized. However, in the absence of simplified_prior = TRUE, we have not yet specified the prior distribution for the dose-toxicity model.
OncoBayes2 provides two methods for completing the model specification:
Use simplified_prior = TRUE, which employs a package-default prior distribution, subject to a small number of optional arguments controlling the details.
Provide a full prior specification to be passed to the main model-fitting engine of OncoBayes2: the blrm_exnex function.
For illustrative purposes, here we highlight method #1. See ?'example-combo2_trial' for an example of #2. The below choice of prior broadly follows the case study in [4], although we slightly deviate from the model in [4] by allowing an EXchangeable/Non-EXchangeable prior for the drug components.
To employ the simplified prior, and fit the model with MCMC:
combo2_trial_start <- blrm_trial(
data = hist_combo2,
drug_info = drug_info_combo2,
dose_info = dose_info,
simplified_prior = TRUE,
EX_prob_comp_hist = 0.8,
EX_prob_comp_new = 1
)Now, the object combo2_trial_start contains the posterior model fit, in addition to the trial design details. Next we highlight the main methods for extracting relevant information from it.
The function prior_summary provides a facility for printing, in a readable format, a summary of the prior specification.
The main target of inference is generally the probability of DLT at a selection of provisional dose levels. To obtain these summaries for the provisional doses specified previously, we simply write:
| group_id | drug_A | drug_B | dose_id | stratum_id | mean | sd | 2.5% | 50% | 97.5% | prob_underdose | prob_target | prob_overdose | ewoc_ok |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| trial_AB | 3 | 0 | 22 | all | 0.08 | 0.12 | 0.00 | 0.04 | 0.44 | 0.86 | 0.10 | 0.04 | TRUE |
| trial_AB | 3 | 400 | 23 | all | 0.14 | 0.16 | 0.00 | 0.09 | 0.63 | 0.72 | 0.18 | 0.10 | TRUE |
| trial_AB | 3 | 600 | 24 | all | 0.16 | 0.17 | 0.01 | 0.11 | 0.68 | 0.65 | 0.23 | 0.12 | TRUE |
| trial_AB | 3 | 800 | 25 | all | 0.20 | 0.18 | 0.02 | 0.15 | 0.73 | 0.53 | 0.31 | 0.16 | TRUE |
Such summaries may be used to assess which combination doses have unacceptable high risk of toxicity. For example, according to the escalation with overdose control (EWOC) design criteria [3], one would compute the posterior probability that each dose is excessively toxic (column prob_overdose; note that the definition of “excessively toxic” is encoded in the blrm_trial object through the interval_prob argument), and take as eligible doses only those where this probability does not exceed 25% (column ewoc_ok).
The BLRM allows a principled approach to predicting the number of DLTs that may be observed in a future cohort. This may be a key estimand for understanding and limiting the toxicity risk to patients. For example, suppose a candidate starting dose for the new trial trial_AB is 3 mg of Drug A + 400 mg of Drug B. We may wish to check that at this dose, the estimated probability of 2 or more DLTs out of an initial cohort of 3 to 6 patients is sufficiently low.
candidate_starting_dose <- summary(combo2_trial_start, "dose_info") %>%
filter(drug_A == 3, drug_B == 400) %>%
expand_grid(num_patients = 3:6) %>%
mutate(num_toxicities = 0)
pp_summary <- summary(combo2_trial_start, interval_prob = c(-1, 0, 1, 6), predictive = TRUE,
newdata = candidate_starting_dose)
kable(bind_cols(select(candidate_starting_dose, num_patients),
select(pp_summary, ends_with("]"))), digits = 3)| num_patients | (-1,0] | (0,1] | (1,6] |
|---|---|---|---|
| 3 | 0.698 | 0.216 | 0.086 |
| 4 | 0.640 | 0.233 | 0.127 |
| 5 | 0.591 | 0.243 | 0.166 |
| 6 | 0.550 | 0.248 | 0.202 |
This tells us that for the initial cohort, according to the model, the chance of two or more patients developing DLTs ranges from 8.6% to 20.2%, depending on the number of patients enrolled.
Dose-escalation designs are adaptive in nature, as dosing decisions are made after each sequential cohort. The model must be updated after each new enrollment. If a new cohort of patients is observed, say:
new_cohort <- tibble(group_id = "trial_AB",
drug_A = 3,
drug_B = 400,
num_patients = 5,
num_toxicities = 1)One can update the model to incorporate this new information using update() with add_data equal to the new cohort:
This yields a new blrm_trial object with updated data and posterior summaries. Below is the method for obtaining posterior estimates at the next highest dose of drug A.
kable(summary(combo2_trial_update, "newdata_prediction",
newdata = tibble(group_id = "trial_AB",
drug_A = 4.5,
drug_B = c(400, 600, 800))), digits = 2)## stratum_id not given, but only one stratum defined. Assigning first stratum.
| group_id | drug_A | drug_B | stratum_id | dose_id | mean | sd | 2.5% | 50% | 97.5% | prob_underdose | prob_target | prob_overdose | ewoc_ok |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| trial_AB | 4.5 | 400 | all | NA | 0.16 | 0.12 | 0.02 | 0.13 | 0.47 | 0.59 | 0.31 | 0.10 | TRUE |
| trial_AB | 4.5 | 600 | all | NA | 0.19 | 0.13 | 0.04 | 0.17 | 0.52 | 0.48 | 0.39 | 0.13 | TRUE |
| trial_AB | 4.5 | 800 | all | NA | 0.23 | 0.14 | 0.05 | 0.20 | 0.58 | 0.35 | 0.45 | 0.20 | TRUE |
It may be of interest to test prospectively how this model responds in various scenarios for upcoming cohorts.
This can be done easily by again using update() with the add_data argument. In the code below, we explore 3 possible outcomes for a subsequent cohort enrolled at 3 mg Drug A + 800 mg Drug B, and review the model’s inference at adjacent doses.
# set up two scenarios at the starting dose level
# store them as data frames in a named list
scenarios <- expand_grid(
group_id = "trial_AB",
drug_A = 3,
drug_B = 800,
num_patients = 3,
num_toxicities = 0:2
) %>% split(1:3) %>% setNames(paste(0:2, "DLTs"))
candidate_doses <- expand_grid(
group_id = "trial_AB",
drug_A = c(3, 4.5),
drug_B = c(600, 800)
)
scenario_inference <- lapply(scenarios, function(scenario_newdata) {
# refit the model with each scenario's additional data
scenario_fit <- update(combo2_trial_update, add_data = scenario_newdata)
# summarize posterior at candidate doses
summary(scenario_fit, "newdata_prediction", newdata = candidate_doses)
})| group_id | drug_A | drug_B | stratum_id | dose_id | mean | sd | 2.5% | 50% | 97.5% | prob_underdose | prob_target | prob_overdose | ewoc_ok |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| trial_AB | 3.0 | 600 | all | 24 | 0.14 | 0.09 | 0.02 | 0.12 | 0.35 | 0.68 | 0.29 | 0.03 | TRUE |
| trial_AB | 3.0 | 800 | all | 25 | 0.17 | 0.10 | 0.04 | 0.15 | 0.40 | 0.54 | 0.40 | 0.06 | TRUE |
| trial_AB | 4.5 | 600 | all | NA | 0.15 | 0.09 | 0.03 | 0.13 | 0.37 | 0.63 | 0.32 | 0.05 | TRUE |
| trial_AB | 4.5 | 800 | all | NA | 0.18 | 0.10 | 0.04 | 0.16 | 0.42 | 0.49 | 0.43 | 0.08 | TRUE |
| group_id | drug_A | drug_B | stratum_id | dose_id | mean | sd | 2.5% | 50% | 97.5% | prob_underdose | prob_target | prob_overdose | ewoc_ok |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| trial_AB | 3.0 | 600 | all | 24 | 0.20 | 0.11 | 0.05 | 0.18 | 0.47 | 0.42 | 0.46 | 0.12 | TRUE |
| trial_AB | 3.0 | 800 | all | 25 | 0.24 | 0.12 | 0.07 | 0.22 | 0.53 | 0.28 | 0.52 | 0.21 | TRUE |
| trial_AB | 4.5 | 600 | all | NA | 0.21 | 0.11 | 0.05 | 0.19 | 0.49 | 0.37 | 0.48 | 0.14 | TRUE |
| trial_AB | 4.5 | 800 | all | NA | 0.25 | 0.12 | 0.07 | 0.23 | 0.54 | 0.23 | 0.53 | 0.24 | TRUE |
| group_id | drug_A | drug_B | stratum_id | dose_id | mean | sd | 2.5% | 50% | 97.5% | prob_underdose | prob_target | prob_overdose | ewoc_ok |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| trial_AB | 3.0 | 600 | all | 24 | 0.28 | 0.14 | 0.07 | 0.25 | 0.60 | 0.21 | 0.48 | 0.31 | FALSE |
| trial_AB | 3.0 | 800 | all | 25 | 0.34 | 0.15 | 0.11 | 0.31 | 0.71 | 0.10 | 0.45 | 0.45 | FALSE |
| trial_AB | 4.5 | 600 | all | NA | 0.29 | 0.14 | 0.08 | 0.27 | 0.62 | 0.18 | 0.47 | 0.35 | FALSE |
| trial_AB | 4.5 | 800 | all | NA | 0.35 | 0.15 | 0.12 | 0.33 | 0.71 | 0.09 | 0.42 | 0.50 | FALSE |
In the example of [1], at the time of completion of trial_AB, the following additional data was observed.
| group_id | drug_A | drug_B | num_patients | num_toxicities | cohort_time |
|---|---|---|---|---|---|
| trial_A | 4.5 | 0 | 3 | 0 | 1 |
| trial_A | 6.0 | 0 | 5 | 0 | 1 |
| IIT | 3.0 | 400 | 3 | 0 | 1 |
| IIT | 3.0 | 800 | 7 | 5 | 1 |
| IIT | 4.5 | 400 | 3 | 0 | 1 |
| IIT | 6.0 | 400 | 6 | 0 | 1 |
| IIT | 6.0 | 600 | 3 | 2 | 1 |
| trial_AB | 3.0 | 400 | 3 | 0 | 1 |
| trial_AB | 3.0 | 800 | 6 | 2 | 1 |
| trial_AB | 4.5 | 600 | 10 | 2 | 1 |
| trial_AB | 6.0 | 400 | 10 | 3 | 1 |
Numerous toxicities were observed in the concurrent IIT study. Through the MAC framework, these data can influence the model summaries for trial_AB. Note that we use the update function differently than before, since we specify the entire data-set now we use the data argument.
Model results can be visualized using package functions. See ?plot_toxicity_curve for details.
plot_toxicity_curve(final_fit, x = vars(drug_B), group = vars(group_id, drug_A),
facet_args = list(ncol = 1))[1] Neuenschwander, B., Roychoudhury, S., & Schmidli, H. (2016). On the use of co-data in clinical trials. Statistics in Biopharmaceutical Research, 8(3), 345-354.
[2] Neuenschwander, B., Wandel, S., Roychoudhury, S., & Bailey, S. (2016). Robust exchangeability designs for early phase clinical trials with multiple strata. Pharmaceutical statistics, 15(2), 123-134.
[3] Neuenschwander, B., Branson, M., & Gsponer, T. (2008). Critical aspects of the Bayesian approach to phase I cancer trials. Statistics in medicine, 27(13), 2420-2439.
[4] Neuenschwander, B., Matano, A., Tang, Z., Roychoudhury, S., Wandel, S. Bailey, Stuart. (2014). A Bayesian Industry Approach to Phase I Combination Trials in Oncology. In Statistical methods in drug combination studies (Vol. 69). CRC Press.
## R version 3.6.1 (2019-07-05)
## Platform: x86_64-pc-linux-gnu (64-bit)
## Running under: Ubuntu 16.04.6 LTS
##
## Matrix products: default
## BLAS: /usr/lib/libblas/libblas.so.3.6.0
## LAPACK: /usr/lib/lapack/liblapack.so.3.6.0
##
## locale:
## [1] C
##
## attached base packages:
## [1] stats graphics grDevices utils datasets methods base
##
## other attached packages:
## [1] tibble_2.1.3 tidyr_1.0.0 dplyr_0.8.3 ggplot2_3.2.1
## [5] knitr_1.25 OncoBayes2_0.7-0 Rcpp_1.0.2
##
## loaded via a namespace (and not attached):
## [1] rstan_2.19.3 tidyselect_0.2.5 xfun_0.10
## [4] purrr_0.3.3 colorspace_1.4-1 vctrs_0.2.0
## [7] htmltools_0.4.0 stats4_3.6.1 loo_2.1.0
## [10] yaml_2.2.0 rlang_0.4.0 pkgbuild_1.0.6
## [13] pillar_1.4.2 glue_1.3.1 withr_2.1.2
## [16] matrixStats_0.55.0 lifecycle_0.1.0 plyr_1.8.4
## [19] stringr_1.4.0 munsell_0.5.0 gtable_0.3.0
## [22] codetools_0.2-16 evaluate_0.14 labeling_0.3
## [25] inline_0.3.15 callr_3.3.2 ps_1.3.0
## [28] parallel_3.6.1 bayesplot_1.7.0 rstantools_2.0.0
## [31] highr_0.8 scales_1.0.0 backports_1.1.5
## [34] checkmate_1.9.4 StanHeaders_2.19.2 abind_1.4-5
## [37] gridExtra_2.3 digest_0.6.21 stringi_1.4.3
## [40] processx_3.4.1 grid_3.6.1 cli_1.1.0
## [43] tools_3.6.1 magrittr_1.5 lazyeval_0.2.2
## [46] Formula_1.2-3 crayon_1.3.4 pkgconfig_2.0.3
## [49] zeallot_0.1.0 prettyunits_1.0.2 ggridges_0.5.1
## [52] assertthat_0.2.1 rmarkdown_1.16 R6_2.4.0
## [55] compiler_3.6.1