| Type: | Package |
| Title: | Fast Simulation of Bayesian Optimal Interval Designs for Phase I Trials |
| Version: | 2.1.0 |
| Date: | 2026-10-13 |
| Description: | Design and evaluate phase I dose-finding trials that use the Bayesian optimal interval (BOIN) design of Liu and Yuan (2015) <doi:10.1111/rssc.12089>. Functions are provided to tabulate the decision boundaries, to simulate trials, to estimate the dose-toxicity curve under a monotonicity constraint and to select the maximum tolerated dose. The simulation engine is written in C++ and draws one random variate per patient in enrollment order, which reproduces the reference implementation in the 'BOIN' package trial by trial for a given seed. The traditional 3+3 design is provided as a comparator, with operating characteristics obtained in closed form rather than by simulation. For toxicity that is observed late, the time-to-event BOIN design is provided with the two estimators of Yuan and colleagues (2018) <doi:10.1158/1078-0432.CCR-18-0246> and Lin and Yuan (2020) <doi:10.1093/biostatistics/kxz007>. Patients who arrive while the dose escalation waits can be backfilled to lower doses with the designs of Zhao and colleagues (2024) <doi:10.1158/1078-0432.CCR-23-2585> and Chen and colleagues (2026) <doi:10.1007/s43441-026-00994-0>, the latter with the suspension rules of Chen and colleagues (2025) <doi:10.1158/1078-0432.CCR-24-3669>. Trials of two drugs given together are handled by the drug-combination design of Lin and Yin (2017) <doi:10.1177/0962280215594494>. |
| License: | MIT + file LICENSE |
| Encoding: | UTF-8 |
| Depends: | R (≥ 3.5.0) |
| Imports: | Iso, Rcpp (≥ 1.0.0), stats, utils |
| LinkingTo: | Rcpp |
| Suggests: | BOIN, ggplot2 (≥ 3.4.0), knitr, rmarkdown, spelling, testthat (≥ 3.0.0) |
| Language: | en-US |
| URL: | https://gosukehommaex.github.io/simFastBOIN/, https://github.com/gosukehommaEX/simFastBOIN |
| BugReports: | https://github.com/gosukehommaEX/simFastBOIN/issues |
| Config/testthat/edition: | 3 |
| VignetteBuilder: | knitr |
| Config/roxygen2/version: | 8.0.0 |
| NeedsCompilation: | yes |
| Packaged: | 2026-10-16 08:56:23 UTC; i_lik |
| Author: | Gosuke Homma |
| Maintainer: | Gosuke Homma <my.name.is.gosuke@gmail.com> |
| Repository: | CRAN |
| Date/Publication: | 2026-10-16 09:20:02 UTC |
simFastBOIN: Fast Simulation of Bayesian Optimal Interval Designs
Description
Tools for designing and evaluating phase I dose-finding trials that use the Bayesian optimal interval (BOIN) design of Liu and Yuan (2015). The simulation engine is written in C++ and reproduces the reference implementation in the BOIN package exactly, including the order in which random variates are consumed, so that results obtained with the same seed agree to the last trial.
Design tools
boin_lambdaEscalation and de-escalation interval boundaries.
boin_p_toxThe toxic threshold giving a required de-escalation boundary.
boin_boundaryInteger decision boundaries as a function of sample size.
boin_decision_tableDecision table indexed by DLTs and patients, with print and plot methods.
boin_stopping_tableSafety stopping boundary as a two-row table.
tite_boin_decision_tableDecision table of the time-to-event BOIN design, which treats new patients while earlier DLT data are pending, with print and plot methods.
Simulation tools
sim_boinOperating characteristics for one scenario.
sim_boin_multiOperating characteristics for several scenarios.
boin_simulateRaw trial data from the simulation engine.
boin_isotonicIsotonic estimates of the DLT probability.
boin_select_mtdMTD selection from completed trials.
sim_tite_boinOperating characteristics of the time-to-event BOIN design for one scenario, with trial duration and suspensions of accrual.
sim_tite_boin_multiThe same for several scenarios.
tite_boin_simulateRaw trial data from the time-to-event BOIN engine, with patients arriving over time and DLTs observed late.
Backfilling
sim_bf_boinOperating characteristics of the BOIN design with backfilling (BF-BOIN) for one scenario of DLT and response probabilities.
sim_bf_boin_multiThe same for several scenarios.
bf_boin_simulateRaw trial data from the BF-BOIN engine, with backfilled patients and responses.
sim_be_boinOperating characteristics of BE-BOIN, which combines backfilling with the time-to-event BOIN design, for one scenario.
sim_be_boin_multiThe same for several scenarios.
be_boin_simulateRaw trial data from the BE-BOIN engine.
Drug combinations
sim_comb_boinOperating characteristics of the BOIN drug-combination design of Lin and Yin (2017) for one matrix of DLT probabilities.
sim_comb_boin_multiThe same for several matrices.
comb_boin_simulateRaw trial data from the drug-combination engine.
comb_boin_select_mtdSelection of the MTD combination from completed trials.
comb_boin_nextThe combination for the next cohort of a trial in progress, with print and plot methods.
The 3+3 design
oc_3p3Operating characteristics of the traditional 3+3 design, in closed form.
sim_3p3The same design by simulation, as a check on the closed form.
decision_table_3p3Decision table of the 3+3 design, with print and plot methods.
Author(s)
Maintainer: Gosuke Homma my.name.is.gosuke@gmail.com (ORCID)
Authors:
Gosuke Homma my.name.is.gosuke@gmail.com (ORCID)
References
Liu S. and Yuan, Y. (2015). Bayesian Optimal Interval Designs for Phase I Clinical Trials. Journal of the Royal Statistical Society: Series C, 64, 507-523.
Yan, F., Zhang, L., Zhou, Y., Pan, H., Liu, S. and Yuan, Y. (2020). BOIN: An R Package for Designing Single-Agent and Drug-Combination Dose-Finding Trials Using Bayesian Optimal Interval Designs. Journal of Statistical Software, 94(13), 1-32.
Yuan, Y., Lin, R., Li, D., Nie, L. and Warren, K. E. (2018). Time-to-Event Bayesian Optimal Interval Design to Accelerate Phase I Trials. Clinical Cancer Research, 24(20), 4921-4930.
Lin, R. and Yuan, Y. (2020). Time-to-Event Model-Assisted Designs for Dose-Finding Trials with Delayed Toxicity. Biostatistics, 21(4), 807-824.
Zhao, Y., Yuan, Y., Korn, E. L. and Freidlin, B. (2024). Backfilling Patients in Phase I Dose-Escalation Trials Using Bayesian Optimal Interval Design (BOIN). Clinical Cancer Research, 30(4), 673-679.
Chen, K., Zhao, Y., Takeda, K. and Yuan, Y. (2026). BE-BOIN: A Dose Optimization Design Accommodating Backfill and Late-Onset Toxicity. Therapeutic Innovation and Regulatory Science. doi:10.1007/s43441-026-00994-0
Lin, R. and Yin, G. (2017). Bayesian Optimal Interval Design for Dose Finding in Drug-Combination Trials. Statistical Methods in Medical Research, 26(5), 2155-2167.
See Also
Useful links:
Report bugs at https://github.com/gosukehommaEX/simFastBOIN/issues
Coerce BOIN Decision Boundaries to a Data Frame
Description
Return the integer decision boundaries produced by boin_boundary
as one row per sample size.
Usage
## S3 method for class 'boin_boundary'
as.data.frame(x, row.names = NULL, optional = FALSE, ...)
Arguments
x |
An object of class |
row.names |
Passed on for compatibility with the generic, normally unused. |
optional |
Passed on for compatibility with the generic, normally unused. |
... |
Further arguments, currently ignored. |
Value
A data frame with columns n_pts, escalate_if_dlt_leq,
deescalate_if_dlt_geq and eliminate_if_dlt_geq, plus
stop_if_dlt_geq when the boundaries were built with
extrasafe = TRUE.
Examples
bd <- boin_boundary(target = 0.30, max_n = 18)
as.data.frame(bd)[seq(3, 18, by = 3), ]
Simulate BE-BOIN Trials
Description
Run the BOIN design with backfilling and late-onset toxicity (BE-BOIN) of Chen et al. (2026) over many simulated trials. Dose escalation follows TITE-BOIN, which decides while some patients are still pending; patients who arrive while the escalation is suspended are backfilled to a lower dose that is safe and has shown a response. Every estimate imputes the pending patients, backfilled ones included. Return the patient, DLT, backfill and response counts at every dose together with the duration of each trial.
Usage
be_boin_simulate(
target,
p_true,
p_resp,
n_cohort,
cohort_size,
window,
accrual_rate,
n_cap = 12,
backfill_dose = c("highest", "lowest"),
conflict_dose = c("lowest", "highest"),
no_slot = c("wait", "leave"),
accrual = c("exponential", "uniform", "fixed"),
dlt_time = c("weibull", "uniform"),
late_fraction = 0.5,
resp_window = window,
resp_late_fraction = 0.5,
resp_cor = 0,
max_pending_ratio = 0.49,
min_completed = 0,
min_follow_up = 0.25,
n_trials = 10000,
start_dose = 1,
n_earlystop = 18,
p_saf = NULL,
p_tox = NULL,
cutoff_eli = 0.95,
extrasafe = FALSE,
offset = 0.05,
n_earlystop_rule = c("with_stay", "simple"),
seed = 123
)
Arguments
target |
Numeric scalar. Target DLT probability, for example 0.25. |
p_true |
Numeric vector. True DLT probability at each dose level, in increasing dose order. The probability of a DLT within the assessment window. |
p_resp |
Numeric vector of the same length as |
n_cohort |
Integer scalar. Number of cohorts in the dose escalation. |
cohort_size |
Integer scalar or vector. Number of patients per cohort of the dose
escalation. A scalar is used for every cohort. A vector shorter than
|
window |
Numeric scalar. Length of the DLT assessment window. |
accrual_rate |
Numeric scalar. Average number of patients arriving per unit of time, in the
same unit as |
n_cap |
Integer scalar. A dose is no longer backfilled once this many patients, from the dose escalation and from backfilling together, have been treated at it. The dose escalation can still treat patients at the dose. Defaults to 12. |
backfill_dose |
Character scalar. Which dose receives a backfill patient when several are
open: |
conflict_dose |
Character scalar. When the data of several backfilled doses conflict with
those of the current dose, which of them anchors the pooled estimate:
|
no_slot |
Character scalar. What happens to a patient who arrives when neither the
dose escalation nor any backfill dose can take a patient: |
accrual |
Character scalar. Distribution of the times between arrivals:
|
dlt_time |
Character scalar. Distribution of the time to DLT within the window, and of
the time to response within the response window: |
late_fraction |
Numeric scalar strictly between 0 and 1. Share of the DLTs that occur in the second half of the assessment window under the Weibull distribution. Defaults to 0.5. |
resp_window |
Numeric scalar. Length of the window within which a response is observed.
Defaults to |
resp_late_fraction |
Numeric scalar strictly between 0 and 1. Share of the responses that occur in the second half of the response window under the Weibull distribution. Defaults to 0.5. |
resp_cor |
Numeric scalar strictly between -1 and 1. Correlation of the Gaussian copula that links the DLT and the response of a patient; a positive value makes a response more likely in a patient with a DLT. Defaults to 0, independence. |
max_pending_ratio |
Numeric scalar greater than 0 and at most 1. Rule 1 of the design: the
escalation is suspended when the proportion of pending patients at the
current dose exceeds this value, unless the dose is de-escalated whatever
their outcomes. Defaults to 0.49, which suspends when fewer than 51 percent
have completed the assessment, as in Chen et al. (2026). See
|
min_completed |
Integer scalar. While some patients are pending, escalation requires at
least this many patients with a completed assessment. Defaults to 0, which
the design does not use. See |
min_follow_up |
Numeric scalar between 0 and 1. Rule 2 of the design: escalation requires
every pending patient at the current dose to have been followed for at
least this fraction of the window. Defaults to 0.25, as in Chen et al.
(2026). See |
n_trials |
Integer scalar. Number of trials to simulate. Defaults to 10000. |
start_dose |
Integer scalar. Dose level for the first cohort. Defaults to 1. |
n_earlystop |
Integer scalar. The trial stops once this many patients, backfilled ones included, have been treated at the current dose and the design would stay there. Defaults to 18. |
p_saf |
Numeric scalar. Highest DLT probability deemed subtherapeutic.
Defaults to |
p_tox |
Numeric scalar. Lowest DLT probability deemed overly toxic.
Defaults to |
cutoff_eli |
Numeric scalar. Posterior probability cutoff for dose elimination. Defaults to 0.95. |
extrasafe |
Logical scalar. Apply the stricter safety stopping rule at the lowest dose.
Defaults to |
offset |
Numeric scalar between 0 and 0.5. Amount by which |
n_earlystop_rule |
Character scalar, either |
seed |
Integer scalar or |
Details
Dose escalation. The dose for a cohort is decided when its first
patient arrives, with the rules of tite_boin_decision_table
for method = "imputation" and the suspension rules
max_pending_ratio and min_follow_up; every patient at the
current dose counts, backfilled ones included. A suspension lasts until a
decision can be taken again, as in tite_boin_simulate.
Elimination counts every treated patient, the pending ones as without DLT,
and is checked at every dose.
Estimates. The DLT rate at a dose is the single mean imputation
estimate of TITE-BOIN, equation (1) of Chen et al. (2026), and the rate
pooled over several doses adds up the observed and imputed DLTs of each
dose, each imputed with its own posterior mean, and divides by the number of
treated patients, equation (2). Both enter the opening and closing of
backfill doses and the resolution of conflicts, which otherwise follow
bf_boin_simulate. The categories of a backfilled dose for
the conflicts compare its estimate with the escalation and de-escalation
boundaries directly.
End of the trial, arrivals and random numbers are as in
bf_boin_simulate. When no dose is ever opened for
backfilling, for example with every p_resp equal to 0, and with
no_slot = "wait", the trials are identical to those of
tite_boin_simulate with method = "imputation", the
same suspension rules and the same seed.
Chen et al. (2026) report their operating characteristics for scenarios
that are given only as figures, so they cannot be reproduced. The decision
table of their supplementary materials is reproduced by
tite_boin_decision_table, and their trial example is
replayed patient by patient in the tests of the package.
Value
An object of class c("be_boin_trials", "backfill_trials"), with the
components described in bf_boin_simulate.
References
Chen, K., Zhao, Y., Takeda, K. and Yuan, Y. (2026). BE-BOIN: A Dose Optimization Design Accommodating Backfill and Late-Onset Toxicity. Therapeutic Innovation and Regulatory Science. doi:10.1007/s43441-026-00994-0
Chen, K., Chen, T.-Y., Zhang, Y., Lin, R. and Yuan, Y. (2025). Practical Considerations for Using the TITE-BOIN Design to Handle Late-Onset Toxicity or Fast Accrual in Phase I Trials. Clinical Cancer Research, 31(13), 2573-2580.
Zhao, Y., Yuan, Y., Korn, E. L. and Freidlin, B. (2024). Backfilling Patients in Phase I Dose-Escalation Trials Using Bayesian Optimal Interval Design (BOIN). Clinical Cancer Research, 30(4), 673-679.
See Also
bf_boin_simulate, tite_boin_simulate
Examples
# A three month window with two patients a month
trials <- be_boin_simulate(
target = 0.25,
p_true = c(0.04, 0.12, 0.25, 0.43, 0.63),
p_resp = c(0.10, 0.20, 0.30, 0.45, 0.58),
n_cohort = 10,
cohort_size = 3,
window = 3,
accrual_rate = 2,
n_earlystop = 9,
n_trials = 200,
seed = 123
)
trials
summary(trials$duration)
Simulate BF-BOIN Trials
Description
Run the BOIN design with backfilling (BF-BOIN) of Zhao et al. (2024) over many simulated trials. Dose escalation proceeds in fully staggered cohorts with the BOIN decision table; patients who arrive while the escalation waits for the DLT assessment of its current cohort are backfilled to a lower dose that is safe and has shown a response. Return the patient, DLT, backfill and response counts at every dose together with the duration of each trial.
Usage
bf_boin_simulate(
target,
p_true,
p_resp,
n_cohort,
cohort_size,
window,
accrual_rate,
n_cap = 12,
backfill_dose = c("highest", "lowest"),
conflict_dose = c("highest", "lowest"),
no_slot = c("wait", "leave"),
accrual = c("exponential", "uniform", "fixed"),
dlt_time = c("weibull", "uniform"),
late_fraction = 0.5,
resp_window = window,
resp_late_fraction = 0.5,
resp_cor = 0,
n_trials = 10000,
start_dose = 1,
n_earlystop = 18,
p_saf = NULL,
p_tox = NULL,
cutoff_eli = 0.95,
extrasafe = FALSE,
offset = 0.05,
stay_on_1_of_3 = FALSE,
n_earlystop_rule = c("with_stay", "simple"),
seed = 123
)
Arguments
target |
Numeric scalar. Target DLT probability, for example 0.25. |
p_true |
Numeric vector. True DLT probability at each dose level, in increasing dose order. The probability of a DLT within the assessment window. |
p_resp |
Numeric vector of the same length as |
n_cohort |
Integer scalar. Number of cohorts in the dose escalation. |
cohort_size |
Integer scalar or vector. Number of patients per cohort of the dose
escalation. A scalar is used for every cohort. A vector shorter than
|
window |
Numeric scalar. Length of the DLT assessment window. |
accrual_rate |
Numeric scalar. Average number of patients arriving per unit of time, in the
same unit as |
n_cap |
Integer scalar. A dose is no longer backfilled once this many patients, from the dose escalation and from backfilling together, have been treated at it. The dose escalation can still treat patients at the dose. Defaults to 12. |
backfill_dose |
Character scalar. Which dose receives a backfill patient when several are
open: |
conflict_dose |
Character scalar. When the data of several backfilled doses conflict with
those of the current dose, which of them anchors the pooled estimate:
|
no_slot |
Character scalar. What happens to a patient who arrives when neither the
dose escalation nor any backfill dose can take a patient: |
accrual |
Character scalar. Distribution of the times between arrivals:
|
dlt_time |
Character scalar. Distribution of the time to DLT within the window, and of
the time to response within the response window: |
late_fraction |
Numeric scalar strictly between 0 and 1. Share of the DLTs that occur in the second half of the assessment window under the Weibull distribution. Defaults to 0.5. |
resp_window |
Numeric scalar. Length of the window within which a response is observed.
Defaults to |
resp_late_fraction |
Numeric scalar strictly between 0 and 1. Share of the responses that occur in the second half of the response window under the Weibull distribution. Defaults to 0.5. |
resp_cor |
Numeric scalar strictly between -1 and 1. Correlation of the Gaussian copula that links the DLT and the response of a patient; a positive value makes a response more likely in a patient with a DLT. Defaults to 0, independence. |
n_trials |
Integer scalar. Number of trials to simulate. Defaults to 10000. |
start_dose |
Integer scalar. Dose level for the first cohort. Defaults to 1. |
n_earlystop |
Integer scalar. The trial stops once this many patients, backfilled ones included, have been treated at the current dose and the design would stay there. Defaults to 18. |
p_saf |
Numeric scalar. Highest DLT probability deemed subtherapeutic.
Defaults to |
p_tox |
Numeric scalar. Lowest DLT probability deemed overly toxic.
Defaults to |
cutoff_eli |
Numeric scalar. Posterior probability cutoff for dose elimination. Defaults to 0.95. |
extrasafe |
Logical scalar. Apply the stricter safety stopping rule at the lowest dose.
Defaults to |
offset |
Numeric scalar between 0 and 0.5. Amount by which |
stay_on_1_of_3 |
Logical scalar. When |
n_earlystop_rule |
Character scalar, either |
seed |
Integer scalar or |
Details
Dose escalation. Cohorts are fully staggered: the next cohort starts only when every patient of the current one has completed the DLT assessment. The decision then follows the BOIN decision table applied to the patients at the current dose who have completed the assessment, backfilled ones included; pending backfill patients are left out, as in Zhao et al. (2024). Dose elimination is checked at the same moments, with the same completed patients, at every dose.
Backfilling. A patient who arrives while the escalation waits is
backfilled to the highest dose b (or the lowest, with
backfill_dose = "lowest") that is below the current dose, has not
been eliminated, has fewer than n_cap patients, and has a response
observed at b or at a lower dose. A dose is closed for backfilling when its
own DLT rate exceeds the de-escalation boundary and so does the rate pooled
with the next higher dose; the doses above it close with it. The rules are
evaluated whenever a patient arrives, so a closed dose reopens when new data
no longer meet the closing condition.
Conflicts. When the data of a backfilled dose b below the current dose call for a more conservative decision than those of the current dose (Table 2 of Zhao et al., 2024), the decision is taken instead from the data pooled from dose b* to the current dose, where b* is the highest conflicting dose by default. A de-escalation then goes to the highest dose k at or above b* whose data pooled from b* stay at or below the de-escalation boundary, or to b* - 1 if there is none, and to the lowest dose if b* is the lowest.
End of the trial. The trial stops when the escalation has treated
n_cohort cohorts, when n_earlystop is reached with a decision
to stay, or when the lowest dose is eliminated. Backfilling stops with the
escalation. Every enrolled patient is followed to the end of the
assessment, and the data of all patients, backfilled ones included, are
those from which the MTD is selected.
Arrivals and outcomes. Patients arrive one at a time. The DLT of a
patient and its time follow p_true and dlt_time as in
tite_boin_simulate; the response and its time follow
p_resp, resp_window and resp_late_fraction in the same
way, linked to the DLT by resp_cor. Neither article states how
responses are timed or correlated with DLTs. The Weibull time to response
with half of the responses in the second half of the window and the
Gaussian copula follow Takeda et al. (2025), who set the correlation to
0.2; the default here is independence.
Random numbers. The DLT variates of the escalation patients are
drawn from R's stream exactly as in boin_simulate; arrivals
and the variates of backfill patients and of responses come from two
generators of their own seeded with seed. As a result, when no dose
is ever opened for backfilling, for example with every p_resp equal
to 0, the trials are identical to those of boin_simulate with
the same seed.
Agreement with the article. With stay_on_1_of_3 = TRUE,
n_earlystop = 9, accrual = "uniform" and
no_slot = "leave", the operating characteristics of Table 4 of Zhao
et al. (2024) are reproduced within simulation error, durations included.
The article states a Poisson process, but its durations, for BOIN as well
as for BF-BOIN, agree with uniform times between arrivals and patients
turned away while the escalation waits. The trial example of Figure 1 of
the article is replayed patient by patient in the tests of the package.
Value
An object of class c("bf_boin_trials", "backfill_trials"), which is
a list with components
n_pts |
Integer matrix, |
n_tox |
Integer matrix of the same shape, of DLTs, counted once every patient has completed the assessment. |
n_bf |
Integer matrix of the same shape, of backfilled patients. |
n_resp |
Integer matrix of the same shape, of patients with a response within the response window. |
eliminated |
Logical matrix of the same shape, marking doses eliminated during the trial. |
cohorts_used |
Integer vector of dose escalation cohorts treated in each trial. |
stop_reason |
Character vector giving why each trial ended, with the
values of |
duration |
Numeric vector. Time from the first arrival until every enrolled patient has completed the DLT assessment. |
n_suspensions |
Integer vector. Number of dose escalation decisions at which the escalation had to wait. |
time_suspended |
Numeric vector. Total time the escalation waited. |
n_turned_away |
Integer vector. Patients turned away, which happens
only with |
boundary |
The |
settings |
List of the design parameters. |
References
Zhao, Y., Yuan, Y., Korn, E. L. and Freidlin, B. (2024). Backfilling Patients in Phase I Dose-Escalation Trials Using Bayesian Optimal Interval Design (BOIN). Clinical Cancer Research, 30(4), 673-679.
Chen, K., Zhao, Y., Takeda, K. and Yuan, Y. (2026). BE-BOIN: A Dose Optimization Design Accommodating Backfill and Late-Onset Toxicity. Therapeutic Innovation and Regulatory Science. doi:10.1007/s43441-026-00994-0
Takeda, K., Zhu, J. and Hirakawa, A. (2025). BF-BOIN-ET: A Backfill Bayesian Optimal Interval Design Using Efficacy and Toxicity Outcomes for Dose Optimization. Pharmaceutical Statistics, 24(2), e2470.
See Also
be_boin_simulate, boin_simulate
Examples
# Scenario 3 of Zhao et al. (2024)
trials <- bf_boin_simulate(
target = 0.25,
p_true = c(0.04, 0.12, 0.25, 0.43, 0.63),
p_resp = c(0.10, 0.20, 0.30, 0.45, 0.58),
n_cohort = 10,
cohort_size = 3,
window = 1,
accrual_rate = 3,
n_earlystop = 9,
stay_on_1_of_3 = TRUE,
n_trials = 200,
seed = 123
)
trials
colMeans(trials$n_bf)
Integer Decision Boundaries for the BOIN Design
Description
Tabulate, for every attainable number of patients treated at a dose, the number of DLTs that triggers escalation, de-escalation, elimination and, when requested, the stricter safety stopping rule at the lowest dose.
Usage
boin_boundary(
target,
max_n,
p_saf = NULL,
p_tox = NULL,
cutoff_eli = 0.95,
extrasafe = FALSE,
offset = 0.05,
stay_on_1_of_3 = FALSE
)
Arguments
target |
Numeric scalar. Target DLT probability, for example 0.30. |
max_n |
Integer scalar. Largest number of patients that can be treated at a single
dose, which is the number of columns of the resulting table. For a trial with
|
p_saf |
Numeric scalar. Highest DLT probability deemed subtherapeutic.
Defaults to |
p_tox |
Numeric scalar. Lowest DLT probability deemed overly toxic.
Defaults to |
cutoff_eli |
Numeric scalar. Posterior probability cutoff above which a dose is eliminated for toxicity. Defaults to 0.95. |
extrasafe |
Logical scalar. When |
offset |
Numeric scalar between 0 and 0.5. Amount by which |
stay_on_1_of_3 |
Logical scalar. When |
Details
The escalation boundary is floor(lambda_e * n) and the de-escalation
boundary is ceiling(lambda_d * n), with the convention that when
lambda_d * n is a whole number de-escalation requires one more DLT. The
elimination boundary is the smallest positive number of DLTs for which
Pr(p > target | data) exceeds cutoff_eli under a uniform
Beta(1, 1) prior, and is not evaluated before three patients have been
treated. The de-escalation boundary is capped at the elimination boundary.
With the default thresholds these definitions reproduce
BOIN::get.boundary() exactly.
Value
An object of class boin_boundary, which is a list with components
lambda_e |
Escalation interval boundary. |
lambda_d |
De-escalation interval boundary. |
n |
Number of patients, 1 to |
b_esc |
Escalate when the number of DLTs is at most this value. |
b_deesc |
De-escalate when the number of DLTs reaches this value. |
b_elim |
Eliminate the dose when the number of DLTs reaches this value,
|
b_stop |
Safety stopping boundary at the lowest dose, all |
stay_on_1_of_3 |
Whether the modification was requested. |
stay_on_1_of_3_applied |
Whether it changed the boundaries. |
together with the design parameters used.
Staying on one DLT out of three
For some target rates the optimal BOIN decision after one DLT in three
patients is to de-escalate, because the likelihood of overdosing then exceeds
the likelihood of proper dosing. Long practice with the 3+3 design has
nonetheless made staying at the dose the widely accepted choice, and
stay_on_1_of_3 = TRUE aligns the design with that practice by raising
the de-escalation boundary at three patients from one DLT to two. Nothing
else in the table changes.
The modification is applied only where it is meaningful, that is when one DLT
out of three currently triggers de-escalation. It never overrides an
escalation, and it never overrides an elimination, which is a safety rule.
Whether it took effect is reported in stay_on_1_of_3_applied. With the
default thresholds it takes effect for target rates from about 0.098 to
0.279; below that range one DLT out of three already eliminates the dose, and
above it the design already stays.
References
Liu S. and Yuan, Y. (2015). Bayesian Optimal Interval Designs for Phase I Clinical Trials. Journal of the Royal Statistical Society: Series C, 64, 507-523.
See Also
boin_lambda, boin_decision_table
Examples
bd <- boin_boundary(target = 0.30, max_n = 18)
bd
# At a target of 0.25 one DLT out of three de-escalates by default
boin_boundary(target = 0.25, max_n = 18)$b_deesc[3]
# and stays once the modification is switched on
modified <- boin_boundary(target = 0.25, max_n = 18, stay_on_1_of_3 = TRUE)
modified$b_deesc[3]
modified$stay_on_1_of_3_applied
# At a target of 0.30 the design already stays, so nothing changes
boin_boundary(target = 0.30, max_n = 18, stay_on_1_of_3 = TRUE)$stay_on_1_of_3_applied
Decision Table for the BOIN Design
Description
Build the lookup table that maps a pair of DLT and patient counts at the current dose to the dose assignment decision.
Usage
boin_decision_table(
target,
max_n,
p_saf = NULL,
p_tox = NULL,
cutoff_eli = 0.95,
stay_on_1_of_3 = FALSE
)
Arguments
target |
Numeric scalar. Target DLT probability. |
max_n |
Integer scalar. Largest number of patients treated at a single dose. |
p_saf |
Numeric scalar. Highest DLT probability deemed subtherapeutic.
Defaults to |
p_tox |
Numeric scalar. Lowest DLT probability deemed overly toxic.
Defaults to |
cutoff_eli |
Numeric scalar. Posterior probability cutoff for dose elimination. Defaults to 0.95. |
stay_on_1_of_3 |
Logical scalar. When |
Details
The table is derived from boin_boundary and therefore agrees
with the decisions taken by the simulation engine. Elimination takes
precedence over the other rules, then escalation, then de-escalation.
Value
An object of class boin_decision_table, which is a character matrix
with max_n + 1 rows, labeled by the number of DLTs from 0 to
max_n, and max_n columns, labeled by the number of patients
from 1 to max_n. Entries are "E" to escalate, "S" to
stay, "D" to de-escalate and "DE" to de-escalate and eliminate
the dose together with all higher doses. Combinations with more DLTs than
patients are NA. The object has print and plot methods;
subsetting it returns a plain matrix.
See Also
boin_boundary, plot.boin_decision_table
Examples
decisions <- boin_decision_table(target = 0.30, max_n = 12)
decisions
# Only the sample sizes reached at the end of a cohort of three
print(decisions, cohort_size = 3)
# One DLT out of three de-escalates at a target of 0.25
boin_decision_table(target = 0.25, max_n = 9)["1", "3"]
# and stays once the modification is switched on
boin_decision_table(target = 0.25, max_n = 9, stay_on_1_of_3 = TRUE)["1", "3"]
Isotonic Estimates of the DLT Probability
Description
Estimate the DLT probability at each dose under the constraint that toxicity does not decrease with dose, using the pool adjacent violators algorithm.
Usage
boin_isotonic(n_pts, n_tox, admissible = NULL)
Arguments
n_pts |
Integer matrix with one row per trial and one column per dose, or a vector for a single trial, giving the number of patients treated. |
n_tox |
Integer matrix or vector of the same shape as |
admissible |
Logical matrix of the same shape as |
Details
Pseudo-counts of 0.05 DLTs and 0.1 patients are added before the fit, and
doses are pooled with inverse variance weights. Doses left out through
admissible do not influence the estimates of the remaining doses,
which matters when eliminated doses must be excluded before selecting the
MTD.
Value
A numeric matrix with one row per trial and one column per dose. Doses that
did not enter the estimation are NA.
References
Liu S. and Yuan, Y. (2015). Bayesian Optimal Interval Designs for Phase I Clinical Trials. Journal of the Royal Statistical Society: Series C, 64, 507-523.
See Also
Examples
# A single trial
boin_isotonic(n_pts = c(3, 6, 9, 12), n_tox = c(0, 1, 3, 4))
# Several trials at once
n_pts <- matrix(c(3, 6, 9, 12,
3, 6, 9, 12,
3, 6, 9, 12), nrow = 3, byrow = TRUE)
n_tox <- matrix(c(0, 1, 3, 4,
0, 0, 2, 3,
1, 2, 4, 6), nrow = 3, byrow = TRUE)
boin_isotonic(n_pts, n_tox)
Escalation and De-escalation Interval Boundaries
Description
Compute the two boundaries that define the BOIN decision interval. A dose is
escalated when the observed DLT rate falls at or below lambda_e and
de-escalated when it reaches lambda_d.
Usage
boin_lambda(target, p_saf = NULL, p_tox = NULL)
Arguments
target |
Numeric scalar. Target DLT probability, for example 0.30. |
p_saf |
Numeric scalar. Highest DLT probability deemed subtherapeutic, so that dose
escalation should be undertaken. Defaults to |
p_tox |
Numeric scalar. Lowest DLT probability deemed overly toxic, so that dose
de-escalation is required. Defaults to |
Details
The boundaries minimize the probability of incorrect dose assignment under a
three-point hypothesis on the DLT probability at the current dose. Values of
p_saf and p_tox close to target should be avoided,
because the sample sizes of phase I trials cannot distinguish the target rate
from rates close to it.
Value
A list with components lambda_e and lambda_d.
References
Liu S. and Yuan, Y. (2015). Bayesian Optimal Interval Designs for Phase I Clinical Trials. Journal of the Royal Statistical Society: Series C, 64, 507-523.
Examples
boin_lambda(target = 0.30)
boin_lambda(target = 0.25, p_saf = 0.12, p_tox = 0.40)
Toxic Threshold Giving a Required De-escalation Boundary
Description
Find the value of p_tox for which the BOIN de-escalation boundary
lambda_d equals a required value. This inverts
boin_lambda, which maps p_tox to lambda_d.
Usage
boin_p_tox(target, lambda_d)
Arguments
target |
Numeric scalar. Target DLT probability. |
lambda_d |
Numeric scalar. Required de-escalation boundary. Must lie strictly between
|
Details
lambda_d increases strictly with p_tox, from target in
the limit as p_tox approaches target to 1 in the limit as
p_tox approaches 1, so the solution exists and is unique for any
lambda_d strictly between those bounds. The root is found
numerically.
A boundary close to the target needs a toxic threshold close to the target,
and the rest of the package refuses a p_tox within ten percent of
target, on the grounds that phase I sample sizes cannot tell the two
rates apart. The value is still returned, since the inversion is well
defined, but a warning names the smallest boundary that leaves a usable
threshold. For a target of 0.30 that smallest boundary is about 0.315.
A design team that wants to tighten the de-escalation boundary usually
states the boundary rather than the threshold behind it. This function turns
that statement into the p_tox to pass to the other functions, so that
the whole design follows from it.
Value
A numeric scalar, the value of p_tox that produces lambda_d.
See Also
Examples
# A target of 0.30 gives a de-escalation boundary of 0.359 by default
boin_lambda(target = 0.30)$lambda_d
# The toxic threshold that tightens it to 0.33
p_tox <- boin_p_tox(target = 0.30, lambda_d = 0.33)
p_tox
# which is what it claims to be
boin_lambda(target = 0.30, p_tox = p_tox)$lambda_d
# A boundary too close to the target leaves an unusable threshold, and says so
boin_p_tox(target = 0.30, lambda_d = 0.31)
# and shifts the de-escalation boundary down by one DLT at every cohort end
as.data.frame(boin_boundary(0.30, 18))[seq(3, 18, 3), ]
as.data.frame(boin_boundary(0.30, 18, p_tox = p_tox))[seq(3, 18, 3), ]
Select the MTD from Completed Trials
Description
Choose the maximum tolerated dose for each of a set of completed trials from the final patient and DLT counts.
Usage
boin_select_mtd(
n_pts,
n_tox,
target,
cutoff_eli = 0.95,
extrasafe = FALSE,
offset = 0.05,
bound_mtd = FALSE,
p_tox = NULL,
mtd_max_estimate = NULL,
min_mtd_sample = 1
)
Arguments
n_pts |
Integer matrix with one row per trial and one column per dose, or a vector for a single trial, giving the number of patients treated. |
n_tox |
Integer matrix or vector of the same shape as |
target |
Numeric scalar. Target DLT probability. |
cutoff_eli |
Numeric scalar. Posterior probability cutoff for dose elimination. Defaults to 0.95. |
extrasafe |
Logical scalar. Apply the stricter safety rule at the lowest dose, in which
case no dose is selected when the lowest dose is judged too toxic.
Defaults to |
offset |
Numeric scalar between 0 and 0.5. Amount by which |
bound_mtd |
Logical scalar. Require the isotonic estimate at the selected dose to be at
or below the de-escalation boundary. Defaults to |
p_tox |
Numeric scalar. Lowest DLT probability deemed overly toxic, used to derive
the de-escalation boundary when |
mtd_max_estimate |
Numeric scalar or |
min_mtd_sample |
Integer scalar. Smallest number of patients a dose must have received to be eligible. Defaults to 1, which admits every dose that treated a patient. |
Details
Dose elimination is re-derived from the final data of each trial rather than
carried over from the dose-finding stage, which is what the reference
implementation does and which matters when a trial ends at its maximum sample
size. The isotonic fit is computed over the admissible doses only, so that
eliminated doses do not influence the estimates of the doses that remain. The
dose whose estimate is closest to target is selected, with ties broken
by a small increasing perturbation across the admissible doses.
bound_mtd caps the estimate at the de-escalation boundary, which
always lies above target. A cap at or below the target rate therefore
cannot be expressed that way, and needs mtd_max_estimate. The two
caps are independent of the decision table, so bounding the selection does
not change how the trial was run.
Values of reason are "selected",
"lowest_dose_eliminated", "no_admissible_dose" and
"no_dose_below_bound".
Value
A data frame with one row per trial and columns
trial |
Trial index. |
mtd |
Selected dose level, or |
reason |
Why the dose was or was not selected. |
References
Liu S. and Yuan, Y. (2015). Bayesian Optimal Interval Designs for Phase I Clinical Trials. Journal of the Royal Statistical Society: Series C, 64, 507-523.
See Also
Examples
n_pts <- matrix(c(3, 6, 9, 3,
3, 6, 9, 3), nrow = 2, byrow = TRUE)
n_tox <- matrix(c(0, 1, 3, 2,
0, 1, 2, 1), nrow = 2, byrow = TRUE)
boin_select_mtd(n_pts, n_tox, target = 0.30)
boin_select_mtd(n_pts, n_tox, target = 0.30, bound_mtd = TRUE)
# Require the isotonic estimate at the selected dose to be at most 0.30,
# which the de-escalation boundary cannot express
boin_select_mtd(n_pts, n_tox, target = 0.30, mtd_max_estimate = 0.30)
Simulate BOIN Trials
Description
Run the BOIN dose-finding algorithm over many simulated trials and return the
patient and DLT counts at every dose. This is the simulation engine behind
sim_boin, exposed for users who want the raw trial data.
Usage
boin_simulate(
target,
p_true,
n_cohort,
cohort_size,
n_trials = 10000,
start_dose = 1,
n_earlystop = 18,
p_saf = NULL,
p_tox = NULL,
cutoff_eli = 0.95,
extrasafe = FALSE,
offset = 0.05,
titration = FALSE,
stay_on_1_of_3 = FALSE,
n_earlystop_rule = c("with_stay", "simple"),
seed = 123
)
Arguments
target |
Numeric scalar. Target DLT probability, for example 0.30. |
p_true |
Numeric vector. True DLT probability at each dose level, in increasing dose order. |
n_cohort |
Integer scalar. Number of cohorts in a trial. |
cohort_size |
Integer scalar or vector. Number of patients per cohort. A scalar is used for
every cohort. A vector shorter than |
n_trials |
Integer scalar. Number of trials to simulate. Defaults to 10000. |
start_dose |
Integer scalar. Dose level for the first cohort. Defaults to 1. It is
ignored when |
n_earlystop |
Integer scalar. The trial stops once this many patients have been treated at the current dose and the design would stay there. Defaults to 18. |
p_saf |
Numeric scalar. Highest DLT probability deemed subtherapeutic.
Defaults to |
p_tox |
Numeric scalar. Lowest DLT probability deemed overly toxic.
Defaults to |
cutoff_eli |
Numeric scalar. Posterior probability cutoff for dose elimination. Defaults to 0.95. |
extrasafe |
Logical scalar. Apply the stricter safety stopping rule at the lowest dose.
Defaults to |
offset |
Numeric scalar between 0 and 0.5. Amount by which |
titration |
Logical scalar. Start with single patient cohorts until the first DLT is
seen. Ignored when the first cohort size is one. Defaults to |
stay_on_1_of_3 |
Logical scalar. When |
n_earlystop_rule |
Character scalar, either |
seed |
Integer scalar or |
Details
One uniform variate is drawn per patient, in enrollment order. Two details
matter for reproducibility: the titration phase draws one variate per dose
level whether or not it is used, and a cohort cut short by the maximum
sample size still draws a full cohort's worth. This is the random number
consumption of BOIN::get.oc(), so with the same seed and matching
arguments a run reproduces the reference implementation trial by trial.
Possible values of stop_reason are "lowest_dose_eliminated",
"lowest_dose_too_toxic", "n_earlystop",
"max_sample_size" and "max_cohorts".
Value
An object of class boin_trials, which is a list with components
n_pts |
Integer matrix, |
n_tox |
Integer matrix of the same shape, of DLTs observed. |
eliminated |
Logical matrix of the same shape, marking doses eliminated during the trial. |
cohorts_used |
Integer vector of cohorts completed in each trial. |
stop_reason |
Character vector giving why each trial ended. |
boundary |
The |
settings |
List of the design parameters. |
References
Liu S. and Yuan, Y. (2015). Bayesian Optimal Interval Designs for Phase I Clinical Trials. Journal of the Royal Statistical Society: Series C, 64, 507-523.
See Also
Examples
trials <- boin_simulate(
target = 0.30,
p_true = c(0.05, 0.15, 0.30, 0.45, 0.60),
n_cohort = 10,
cohort_size = 3,
n_trials = 200,
seed = 123
)
trials
head(trials$n_pts)
table(trials$stop_reason)
Safety Stopping Boundary as a Two-Row Table
Description
Present the safety stopping boundary at the lowest dose as a compact table with one column per sample size, which is the shape usually wanted in a protocol or a report.
Usage
boin_stopping_table(x, cohort_size = NULL)
Arguments
x |
An object of class |
cohort_size |
Integer scalar or |
Details
The same numbers are available one row per sample size from
as.data.frame() on the boundary object. This function transposes them
and labels the rows, which suits a table pasted into a document or rendered
with knitr::kable() or DT::datatable().
Value
A data frame with two rows, labeled by the quantity they hold, and one column per sample size. Sample sizes at which no number of DLTs triggers the rule are dropped.
See Also
Examples
bd <- boin_boundary(target = 0.30, max_n = 18, extrasafe = TRUE)
boin_stopping_table(bd)
# Only the sample sizes reached at the end of a cohort of three
boin_stopping_table(bd, cohort_size = 3)
Next Dose Combination in a BOIN Drug-Combination Trial
Description
Decide the dose combination for the next cohort of a trial run with the
BOIN drug-combination design of Lin and Yin (2017), from the numbers of
patients and DLTs observed so far at every combination and the combination
that treated the last cohort. The rules are those of
comb_boin_simulate, so the decisions taken during the trial
are the ones whose operating characteristics sim_comb_boin
reports.
Usage
comb_boin_next(
target,
n_pts,
n_tox,
current,
n_earlystop = 18,
p_saf = NULL,
p_tox = NULL,
cutoff_eli = 0.95,
extrasafe = FALSE,
offset = 0.05
)
Arguments
target |
Numeric scalar. Target DLT probability, for example 0.30. |
n_pts |
Integer matrix. Number of patients treated so far at each dose combination, with one row per dose level of drug A and one column per dose level of drug B. |
n_tox |
Integer matrix of the same shape as |
current |
Integer vector of length two. Dose levels of drug A and drug B of the combination that treated the last cohort. |
n_earlystop |
Integer scalar. The trial stops once this many patients have been treated at the current combination and the design would neither escalate nor de-escalate, or cannot. Defaults to 18. Use the value of the simulations that support the protocol. |
p_saf |
Numeric scalar. Highest DLT probability deemed subtherapeutic.
Defaults to |
p_tox |
Numeric scalar. Lowest DLT probability deemed overly toxic.
Defaults to |
cutoff_eli |
Numeric scalar. Posterior probability cutoff for eliminating a combination. Defaults to 0.95. |
extrasafe |
Logical scalar. Apply the stricter safety stopping rule at the lowest
combination. Defaults to |
offset |
Numeric scalar between 0 and 0.5. Amount by which |
Details
The decision follows the same steps as a simulated trial after each
cohort. A combination whose DLT count reaches its elimination boundary is
eliminated together with every combination with at least the same level of
both drugs, and the trial stops if the lowest combination is eliminated or,
with extrasafe, judged too toxic. The trial also stops when
n_earlystop patients have been treated at the current combination
and the design would neither escalate nor de-escalate. Otherwise the
observed DLT rate at the current combination is compared with the
boundaries of boin_boundary, and an escalation or a
de-escalation moves one level of drug A or of drug B to the candidate with
the higher score: the posterior probability, under a Beta(0.5, 0.5) prior,
that its DLT rate lies between lambda_e and lambda_d, plus
0.0005 per patient already treated there. An eliminated combination is not
a candidate for escalation. When the two scores are equal the design
chooses at random, and the function returns both.
During a simulated trial a combination is eliminated as soon as its data reach the boundary and is never treated again, so the combinations eliminated by the data are exactly those eliminated in the course of the trial.
BOIN::next.comb() applies somewhat different rules from the
simulations of BOIN::get.oc.comb(): it stops as soon as
n.earlystop patients have been treated at the current combination,
it does not escalate drug A when a combination with the next level of drug
A and at most the current level of drug B has an observed DLT rate at or
above lambda_d (and likewise for drug B), and it draws a random
number to break ties. This function follows the simulations instead, so
that a trial is run with the rules whose operating characteristics were
evaluated. Where the rules coincide, the two functions agree.
Value
An object of class comb_boin_next, which is a list with components
decision |
One of |
next_dose |
Integer matrix with columns |
tie |
Whether two candidates tie, in which case the design picks one of them at random. |
stop_reason |
|
note |
A sentence explaining a decision to stay when the rule called for a move that is not available, otherwise |
candidates |
Data frame of the two combinations considered for an escalation or a de-escalation, one level of drug A and one level of drug B away, with their data, the posterior probability that their DLT rate lies between |
eliminated |
Logical matrix of the combinations eliminated by the data. |
boundary |
The escalation, de-escalation and elimination boundaries at the number of patients treated at the current combination. |
together with the data, the current combination and the design parameters.
References
Lin, R. and Yin, G. (2017). Bayesian Optimal Interval Design for Dose Finding in Drug-Combination Trials. Statistical Methods in Medical Research, 26(5), 2155-2167.
See Also
plot.comb_boin_next, boin_decision_table,
sim_comb_boin
Examples
# Three levels of drug A and four of drug B; the last cohort was treated at
# A2B2, where two of three patients had a DLT
n_pts <- matrix(c(6, 6, 0, 0,
3, 3, 0, 0,
0, 0, 0, 0), nrow = 3, byrow = TRUE)
n_tox <- matrix(c(0, 1, 0, 0,
1, 2, 0, 0,
0, 0, 0, 0), nrow = 3, byrow = TRUE)
nxt <- comb_boin_next(target = 0.25, n_pts = n_pts, n_tox = n_tox,
current = c(2, 2))
nxt
nxt$next_dose
Select the MTD Combination from Completed Drug-Combination Trials
Description
Choose the maximum tolerated dose combination for each of a set of completed trials of the BOIN drug-combination design from the final patient and DLT counts.
Usage
comb_boin_select_mtd(
n_pts,
n_tox,
target,
cutoff_eli = 0.95,
extrasafe = FALSE,
offset = 0.05,
bound_mtd = FALSE,
p_tox = NULL
)
Arguments
n_pts |
Integer matrix giving the number of patients treated at each combination of
one trial, with one row per dose level of drug A and one column per dose
level of drug B, or an integer array with dimensions trial by level of drug
A by level of drug B for several trials, as returned by
|
n_tox |
Integer matrix or array of the same shape as |
target |
Numeric scalar. Target DLT probability. |
cutoff_eli |
Numeric scalar. Posterior probability cutoff for eliminating a combination. Defaults to 0.95. |
extrasafe |
Logical scalar. Apply the stricter safety rule at the lowest combination, in
which case no combination is selected when it is judged too toxic.
Defaults to |
offset |
Numeric scalar between 0 and 0.5. Amount by which |
bound_mtd |
Logical scalar. Require the isotonic estimate at the selected combination
to be below the de-escalation boundary. Defaults to |
p_tox |
Numeric scalar. Lowest DLT probability deemed overly toxic, used to derive
the de-escalation boundary when |
Details
The selection follows the reference implementation used by
BOIN::get.oc.comb(). Elimination is re-derived from the final data:
within each row, the first combination with at least three patients whose
posterior probability of a DLT rate above target exceeds
cutoff_eli is eliminated together with the rest of its row and the
rest of its column. If the lowest combination is eliminated, no
combination is selected. Otherwise the estimates
(y + 0.05) / (n + 0.1) are smoothed by bivariate isotonic regression
with weights
n + 0.1, so that they increase along every row and column, and the
treated, non-eliminated combination whose estimate is closest to
target is selected. A small amount, 1e-5 times the sum of
the two dose levels, is added to every estimate first, so that ties go to
the lower combination.
The isotonic regression is Iso::biviso(), the routine the reference
implementation calls. Combinations that the regression pools together have
equal estimates in exact arithmetic but can differ in the last digits, and
with the small amount above, these digits decide between combinations on
the same anti-diagonal. Another algorithm for the same regression would
therefore select differently in a few trials out of a thousand.
The article of Lin and Yin (2017) estimates the DLT rates as y / n
and resolves ties differently; the package follows the reference
implementation so that the two can be compared trial by trial.
Values of reason are "selected",
"lowest_dose_eliminated" and "no_dose_below_bound".
Value
A data frame with one row per trial and columns
trial |
Trial index. |
mtd_a |
Dose level of drug A in the selected combination, or |
mtd_b |
Dose level of drug B in the selected combination, or |
reason |
Why a combination was or was not selected. |
References
Lin, R. and Yin, G. (2017). Bayesian Optimal Interval Design for Dose Finding in Drug-Combination Trials. Statistical Methods in Medical Research, 26(5), 2155-2167.
See Also
comb_boin_simulate, sim_comb_boin
Examples
n_pts <- matrix(c(3, 6, 3,
3, 3, 0), nrow = 2, byrow = TRUE)
n_tox <- matrix(c(0, 1, 1,
0, 2, 0), nrow = 2, byrow = TRUE)
comb_boin_select_mtd(n_pts, n_tox, target = 0.30)
Simulate BOIN Drug-Combination Trials
Description
Run the BOIN drug-combination design of Lin and Yin (2017) over many
simulated trials of two drugs given together, and return the patient and
DLT counts at every dose combination. This is the simulation engine behind
sim_comb_boin, exposed for users who want the raw trial data.
Usage
comb_boin_simulate(
target,
p_true,
n_cohort,
cohort_size,
n_trials = 10000,
start_dose = c(1, 1),
n_earlystop = 18,
p_saf = NULL,
p_tox = NULL,
cutoff_eli = 0.95,
extrasafe = FALSE,
offset = 0.05,
titration = FALSE,
seed = 123
)
Arguments
target |
Numeric scalar. Target DLT probability, for example 0.30. |
p_true |
Numeric matrix. True DLT probability of each dose combination, with one row per dose level of drug A and one column per dose level of drug B, both in increasing dose order. |
n_cohort |
Integer scalar. Number of cohorts in a trial. |
cohort_size |
Integer scalar or vector. Number of patients per cohort. A scalar is used for
every cohort. A vector shorter than |
n_trials |
Integer scalar. Number of trials to simulate. Defaults to 10000. |
start_dose |
Integer vector of length two. Dose levels of drug A and drug B for the first
cohort. Defaults to |
n_earlystop |
Integer scalar. The trial stops once this many patients have been treated at the current combination and the design would neither escalate nor de-escalate, or cannot. Defaults to 18. Set it to a value above the maximum sample size to switch this rule off. |
p_saf |
Numeric scalar. Highest DLT probability deemed subtherapeutic.
Defaults to |
p_tox |
Numeric scalar. Lowest DLT probability deemed overly toxic.
Defaults to |
cutoff_eli |
Numeric scalar. Posterior probability cutoff for eliminating a combination. Defaults to 0.95. |
extrasafe |
Logical scalar. Apply the stricter safety stopping rule at the lowest
combination. Defaults to |
offset |
Numeric scalar between 0 and 0.5. Amount by which |
titration |
Logical scalar. Treat one patient per combination, moving up one level of
either drug, until the first DLT, before switching to full cohorts. Ignored
when the first cohort size is one. Defaults to |
seed |
Integer scalar or |
Details
The decision boundaries are those of the single-agent design, from
boin_boundary. After each cohort the observed DLT rate at the
current combination is compared with them. When the design escalates, the
next cohort goes one level up of drug A or of drug B, whichever has the
larger posterior probability, under a Beta(0.5, 0.5) prior, that its DLT
probability lies between lambda_e and lambda_d; de-escalation
chooses one level down in the same way. Eliminated combinations are not
escalated to. When a combination is eliminated, so is every combination
with at least the same level of both drugs, and the trial stops when the
lowest combination is eliminated.
The rules, and the order in which they are applied, are those of
BOIN::get.oc.comb() with mtd.contour = FALSE. That
implementation adds two things to the article: a candidate's posterior
probability is increased by 0.0005 for every patient already treated
there, so that ties go to the better informed combination, and the trial
can stop at n_earlystop. Random variates are
drawn in the same order as there: one per patient, one for the direction
of every titration step that can go either way, and one for every
escalation or de-escalation that has a candidate, even when there is only
one. With the same seed and matching arguments a run therefore reproduces
the reference implementation trial by trial.
During titration the patients treated before the first DLT are added to
the planned cohorts, as in the reference implementation: the first full
cohort only tops up the combination reached. A trial can therefore treat a
few more patients than n_cohort cohorts hold.
Possible values of stop_reason are "lowest_dose_eliminated",
"lowest_dose_too_toxic", "n_earlystop" and
"max_cohorts".
Value
An object of class comb_boin_trials, which is a list with components
n_pts |
Integer array of patients treated, with dimensions trial by level of drug A by level of drug B. |
n_tox |
Integer array of the same shape, of DLTs observed. |
eliminated |
Logical array of the same shape, marking combinations eliminated during the trial. |
cohorts_used |
Integer vector of cohorts completed in each trial. |
stop_reason |
Character vector giving why each trial ended. |
boundary |
The |
settings |
List of the design parameters. |
References
Lin, R. and Yin, G. (2017). Bayesian Optimal Interval Design for Dose Finding in Drug-Combination Trials. Statistical Methods in Medical Research, 26(5), 2155-2167.
Yan, F., Zhang, L., Zhou, Y., Pan, H., Liu, S. and Yuan, Y. (2020). BOIN: An R Package for Designing Single-Agent and Drug-Combination Dose-Finding Trials Using Bayesian Optimal Interval Designs. Journal of Statistical Software, 94(13), 1-32.
See Also
sim_comb_boin, comb_boin_select_mtd
Examples
p_true <- matrix(c(0.02, 0.04, 0.08, 0.14,
0.08, 0.25, 0.42, 0.48,
0.25, 0.45, 0.50, 0.60), nrow = 3, byrow = TRUE)
trials <- comb_boin_simulate(
target = 0.25,
p_true = p_true,
n_cohort = 16,
cohort_size = 3,
n_trials = 200,
seed = 123
)
trials
# Patients treated at each combination in the first trial
trials$n_pts[1, , ]
Decision Table for the 3+3 Design
Description
Tabulate the dose assignment rule of the traditional 3+3 design used by
oc_3p3 and sim_3p3: for every number of DLTs
among the three or six patients treated at the current dose, the decision
taken during dose escalation and, for mtd_rule = "expand", during the
search for the MTD that follows it.
Usage
decision_table_3p3(mtd_rule = c("previous", "expand"))
Arguments
mtd_rule |
Character scalar, either |
Details
During escalation three patients are treated at the current dose. No DLT escalates, one DLT adds three more patients at the same dose, and two or more stop escalation. With six patients, at most one DLT escalates and two or more stop escalation. Escalating from the highest dose also ends escalation.
With mtd_rule = "previous" the MTD is the dose below the one at which
escalation stopped, or the highest dose when it was escalated from, and no
MTD is selected when escalation stops at the starting dose. With
mtd_rule = "expand" the search starts at the dose below the one at
which escalation stopped, or at the highest dose when it was escalated from.
A dose with three patients receives three more; a dose with at most one DLT
out of six is selected as the MTD, and one with two or more passes the search
to the next lower dose. No MTD is selected when the search moves below the
starting dose.
Every number of DLTs from 0 to n is listed for six patients, although
in a trial the six patients at a dose during escalation always include one
DLT among the first three. The search examines only doses that were
escalated from, so a dose with three patients has no DLT there, and only that
state is listed.
The rules are those of oc_3p3: the tests follow this table
through every possible course of a trial and obtain the operating
characteristics of oc_3p3().
Value
An object of class decision_table_3p3, which is a data frame with one
row per state of the current dose and the columns
stage |
|
n |
Number of patients treated at the current dose, 3 or 6. |
n_tox |
Number of patients with a DLT, from 0 to |
decision |
Decision code. During escalation, |
The definition of the MTD is stored in the attribute mtd_rule. The
object has print and plot methods.
See Also
print.decision_table_3p3,
plot.decision_table_3p3, oc_3p3,
boin_decision_table
Examples
decision_table_3p3()
# The other definition of the MTD adds the search for the MTD
decision_table_3p3(mtd_rule = "expand")
Exact Operating Characteristics of the 3+3 Design
Description
Compute the operating characteristics of the traditional 3+3 dose-finding
design exactly. The probability of every path the design can take is
evaluated in closed form, so the result carries no Monte Carlo error and no
seed is involved. Use it as a comparator for the BOIN results returned by
sim_boin.
Usage
oc_3p3(
p_true,
mtd_rule = c("previous", "expand"),
start_dose = 1,
overdose_cutoff = NULL
)
Arguments
p_true |
Numeric vector. True DLT probability at each dose level, in increasing dose order. |
mtd_rule |
Character scalar, either |
start_dose |
Integer scalar. Dose level for the first cohort. Defaults to 1. |
overdose_cutoff |
Numeric scalar or |
Details
The escalation rule is the traditional one. Three patients are treated at the current dose. No DLT leads to the next dose up. One DLT out of three leads to three more patients at the same dose, and then to the next dose up if no further DLT is seen and to stopping otherwise. Two or more DLTs out of three stop the trial at once. A trial that escalates past the highest dose ends there.
The two MTD rules differ only in what happens once escalation has stopped.
"previous" names the dose below the one declared too toxic, and the
highest dose when escalation ran out of doses. "expand" instead takes
the MTD to be the highest dose at which at most one of six patients had a
DLT: starting from the highest dose still eligible, a dose that has only
three patients is expanded to six and assessed, and the search moves down a
level whenever the expanded dose fails. Neither rule is universally the
standard, so the comparator being matched should be checked before a rule is
chosen. The two agree on which doses are visited during escalation, and so
on the probability that a patient is exposed to an overly toxic dose; they
differ in the sample size and in the selection percentages.
The 3+3 design has no fixed maximum sample size, so the within-trial
exposure percentage and the 60 percent and 80 percent thresholds reported
for BOIN in sim_boin have no counterpart here.
Value
An object of class oc_3p3, which is a list with components
sel_percent |
Percentage of trials selecting each dose as the MTD. |
percent_no_mtd |
Percentage of trials ending without an MTD. |
n_pts_dose |
Average number of patients treated at each dose. |
n_tox_dose |
Average number of DLTs observed at each dose. |
total_n_pts |
Average total number of patients per trial. |
total_n_tox |
Average total number of DLTs per trial. |
overdose |
List describing the design's relationship with doses above |
together with p_true, n_doses, mtd_rule,
start_dose, method and the call.
See Also
Examples
oc_3p3(p_true = c(0.30, 0.48, 0.67))
# The other definition of the MTD
oc_3p3(p_true = c(0.30, 0.48, 0.67), mtd_rule = "expand")
# Exposure to doses above a stated DLT rate
oc_3p3(p_true = c(0.20, 0.40, 0.60), overdose_cutoff = 1 / 3)$overdose
Plot a BOIN Decision Table
Description
Draw the decision table produced by boin_decision_table as a
grid of colored cells, one per pair of DLT and patient counts, with the
decision letter in each cell.
Usage
## S3 method for class 'boin_decision_table'
plot(x, text_size = 1, colors = NULL, ...)
Arguments
x |
An object of class |
text_size |
Numeric scalar. Multiplier applied to every text size in the figure. Use a larger value when the figure is exported at high resolution, for example into a report. Defaults to 1. |
colors |
Named character vector of four colors, with names |
... |
Further arguments, currently ignored. |
Details
Every cell carries its decision letter, so the figure does not rely on color alone to convey the decision and remains readable in grayscale.
Requires the ggplot2 package, which is only suggested by simFastBOIN rather than required.
Value
A ggplot2 object, which can be printed, saved with
ggplot2::ggsave() or extended with further layers.
See Also
boin_decision_table, print.boin_decision_table
Examples
decisions <- boin_decision_table(target = 0.30, max_n = 12)
plot(decisions)
# Larger text for a high resolution export
plot(decisions, text_size = 2)
# A palette of your own
plot(decisions, colors = c(E = "#4DAF4A", S = "#377EB8",
D = "#FF7F00", DE = "#E41A1C"))
Plot the Next Dose Combination of a BOIN Drug-Combination Trial
Description
Draw the dose matrix of a drug-combination trial with the data observed at
every combination, the current combination, the combination chosen for the
next cohort and the combinations eliminated, as returned by
comb_boin_next.
Usage
## S3 method for class 'comb_boin_next'
plot(x, text_size = 1, colors = NULL, ...)
Arguments
x |
An object of class |
text_size |
Numeric scalar. Multiplier applied to every text size in the figure. Use a larger value when the figure is exported at high resolution. Defaults to 1. |
colors |
Named character vector of five colors, with names |
... |
Further arguments, currently ignored. |
Details
Each cell shows the number of patients with a DLT and the number treated,
and the status of the current, next and eliminated combinations is also
written in the cell, so the figure does not rely on color alone. The
candidates of an escalation or a de-escalation also show the posterior
probability that their DLT rate lies between lambda_e and
lambda_d. The levels of drug A run up the vertical axis and those of
drug B along the horizontal axis.
Requires the ggplot2 package, which is only suggested by simFastBOIN rather than required.
Value
A ggplot2 object, which can be printed, saved with
ggplot2::ggsave() or extended with further layers.
See Also
Examples
n_pts <- matrix(c(6, 6, 0, 0,
3, 3, 0, 0,
0, 0, 0, 0), nrow = 3, byrow = TRUE)
n_tox <- matrix(c(0, 1, 0, 0,
1, 2, 0, 0,
0, 0, 0, 0), nrow = 3, byrow = TRUE)
nxt <- comb_boin_next(target = 0.25, n_pts = n_pts, n_tox = n_tox,
current = c(2, 2))
plot(nxt)
Plot a 3+3 Decision Table
Description
Draw the decision table produced by decision_table_3p3 as a
grid of colored cells, one per pair of patient and DLT counts, with the
decision code in each cell. With mtd_rule = "expand" the search for
the MTD is drawn in a second panel.
Usage
## S3 method for class 'decision_table_3p3'
plot(x, text_size = 1, colors = NULL, ...)
Arguments
x |
An object of class |
text_size |
Numeric scalar. Multiplier applied to every text size in the figure. Defaults to 1. |
colors |
Named character vector of colors with the names |
... |
Further arguments, currently ignored. |
Details
Every cell carries its decision code, so the figure does not rely on color alone. Requires the ggplot2 package, which is only suggested by simFastBOIN rather than required.
Value
A ggplot2 object, which can be printed, saved with
ggplot2::ggsave() or extended with further layers.
See Also
decision_table_3p3,
print.decision_table_3p3
Examples
plot(decision_table_3p3())
plot(decision_table_3p3(mtd_rule = "expand"))
Plot a TITE-BOIN Decision Table
Description
Draw the decision table produced by tite_boin_decision_table
as one panel per number of patients treated. Within a panel, each cell is a
pair of pending patients and DLTs, colored by its decision and labeled with
the decision code and, where the decision depends on the follow-up of the
pending patients, the boundaries on the follow-up statistic.
Usage
## S3 method for class 'tite_boin_decision_table'
plot(
x,
n = NULL,
cohort_size = NULL,
text_size = 1,
colors = NULL,
digits = 2,
...
)
Arguments
x |
An object of class |
n |
Integer vector or |
cohort_size |
Integer scalar or |
text_size |
Numeric scalar. Multiplier applied to every text size in the figure. Defaults to 1. |
colors |
Named character vector of six colors, with names |
digits |
Integer scalar. Number of decimal places of the boundaries in the labels. Defaults to 2. |
... |
Further arguments, currently ignored. |
Details
A cell whose decision depends on the follow-up statistic shows its codes
over the boundaries, kept short so that they fit in the cell. A label such
as "E/S" over ">=2.15" means that the dose is escalated when
the statistic is at least 2.15 and kept otherwise, and "S/D" over
"<=0.52" that it is de-escalated when the statistic is at most 0.52.
The boundary marked ">=" always belongs to the first code, which is
"E", or "SUS" when escalation is blocked, and the one marked
"<=" to "D". The statistic is STFT for
method = "imputation" and ESS for method = "ess".
When the table was built with a positive min_follow_up, the code of
a cell whose escalation also requires the shortest follow-up of the pending
patients to reach that fraction of the window is marked with an asterisk,
as in "E*" or "E/S*", and a caption explains the mark.
Every cell carries its decision code, so the figure does not rely on color
alone. With many panels, or many patients per panel, the cells become small;
draw fewer panels through n, enlarge the figure, or lower
text_size. Requires the ggplot2 package, which is only
suggested by simFastBOIN rather than required.
Value
A ggplot2 object, which can be printed, saved with
ggplot2::ggsave() or extended with further layers.
See Also
tite_boin_decision_table,
print.tite_boin_decision_table
Examples
decisions <- tite_boin_decision_table(target = 0.2, max_n = 15)
plot(decisions, n = c(9, 12, 15))
# Every cohort end, with smaller text
plot(decisions, cohort_size = 3, text_size = 0.8)
Print Operating Characteristics of a BOIN Design with Backfilling
Description
Display the result of sim_bf_boin or
sim_be_boin: the design, a table by dose of the true DLT and
response rates, the MTD selection, the patients treated and backfilled and
the DLTs, then the exposure above the overdose cutoff and the timing.
Usage
## S3 method for class 'backfill_oc'
print(
x,
digits = 1,
percent = FALSE,
kable = FALSE,
kable_format = "pipe",
...
)
Arguments
x |
An object of class |
digits |
Integer scalar. Number of decimal places. Defaults to 1. |
percent |
Logical scalar. Show patients, backfilled patients and DLTs as percentages
of their totals rather than as averages per trial. Defaults to
|
kable |
Logical scalar. Print only the table, formatted by |
kable_format |
Character scalar passed to |
... |
Further arguments, currently ignored. |
Value
The object x, invisibly.
See Also
Examples
oc <- sim_bf_boin(
target = 0.25,
p_true = c(0.04, 0.12, 0.25, 0.43, 0.63),
p_resp = c(0.10, 0.20, 0.30, 0.45, 0.58),
n_cohort = 10, cohort_size = 3, window = 1, accrual_rate = 3,
n_trials = 200, seed = 1
)
print(oc)
print(oc, percent = TRUE)
Print Operating Characteristics of a Backfill Design Across Scenarios
Description
Display the result of sim_bf_boin_multi or
sim_be_boin_multi as one table with seven rows per scenario.
Usage
## S3 method for class 'backfill_oc_multi'
print(
x,
digits = 1,
percent = FALSE,
kable = FALSE,
kable_format = "pipe",
...
)
Arguments
x |
An object of class |
digits |
Integer scalar. Number of decimal places. Defaults to 1. |
percent |
Logical scalar. Show patients, backfilled patients and DLTs as percentages
of their totals. Defaults to |
kable |
Logical scalar. Print only the table, formatted by |
kable_format |
Character scalar passed to |
... |
Further arguments, currently ignored. |
Value
The object x, invisibly.
See Also
sim_bf_boin_multi, sim_be_boin_multi
Examples
scenarios <- list(
list(name = "Rising", p_true = c(0.04, 0.12, 0.25, 0.43, 0.63),
p_resp = c(0.10, 0.20, 0.30, 0.45, 0.58)),
list(name = "Plateau", p_true = c(0.04, 0.12, 0.25, 0.43, 0.63),
p_resp = c(0.30, 0.32, 0.35, 0.36, 0.36))
)
oc <- sim_bf_boin_multi(
target = 0.25, scenarios = scenarios, n_cohort = 10, cohort_size = 3,
window = 1, accrual_rate = 3, n_trials = 100, seed = 1
)
print(oc, percent = TRUE)
Print Simulated Trials of a BOIN Design with Backfilling
Description
Summarize the trials returned by bf_boin_simulate or
be_boin_simulate: the design, the average numbers of
patients, backfilled patients, DLTs and responses at each dose, the trial
duration, the waiting of the dose escalation and the reasons for stopping.
Usage
## S3 method for class 'backfill_trials'
print(x, ...)
Arguments
x |
An object of class |
... |
Further arguments, currently ignored. |
Value
The object x, invisibly.
See Also
bf_boin_simulate, be_boin_simulate
Examples
trials <- bf_boin_simulate(
target = 0.25,
p_true = c(0.04, 0.12, 0.25, 0.43, 0.63),
p_resp = c(0.10, 0.20, 0.30, 0.45, 0.58),
n_cohort = 10, cohort_size = 3, window = 1, accrual_rate = 3,
n_trials = 100, seed = 1
)
print(trials)
Print BOIN Decision Boundaries
Description
Display the interval boundaries and the integer decision boundaries produced
by boin_boundary.
Usage
## S3 method for class 'boin_boundary'
print(x, cohort_size = NULL, ...)
Arguments
x |
An object of class |
cohort_size |
Integer scalar or |
... |
Further arguments, currently ignored. |
Value
The object x, invisibly.
Examples
bd <- boin_boundary(target = 0.30, max_n = 18, extrasafe = TRUE)
print(bd, cohort_size = 3)
Print a BOIN Decision Table
Description
Display the decision table produced by boin_decision_table,
optionally restricted to the sample sizes reached at the end of a cohort.
Usage
## S3 method for class 'boin_decision_table'
print(x, cohort_size = NULL, ...)
Arguments
x |
An object of class |
cohort_size |
Integer scalar or |
... |
Further arguments, currently ignored. |
Value
The object x, invisibly.
See Also
boin_decision_table, plot.boin_decision_table
Examples
decisions <- boin_decision_table(target = 0.30, max_n = 18)
print(decisions, cohort_size = 3)
Print Operating Characteristics of a BOIN Design
Description
Display the summary table produced by sim_boin.
Usage
## S3 method for class 'boin_oc'
print(
x,
digits = 1,
percent = FALSE,
kable = FALSE,
kable_format = "pipe",
...
)
Arguments
x |
An object of class |
digits |
Integer scalar. Number of decimal places. Defaults to 1. |
percent |
Logical scalar. Express the average number of patients and DLTs at each dose
as a percentage of the trial total instead of a count. Defaults to
|
kable |
Logical scalar. Return the table through |
kable_format |
Character scalar passed to |
... |
Further arguments, currently ignored. |
Value
The object x, invisibly.
Examples
oc <- sim_boin(
target = 0.30,
p_true = c(0.05, 0.15, 0.30, 0.45, 0.60),
n_cohort = 10,
cohort_size = 3,
n_trials = 200,
seed = 123
)
print(oc)
print(oc, percent = TRUE)
Print Operating Characteristics Across Scenarios
Description
Display the combined summary table produced by sim_boin_multi.
Usage
## S3 method for class 'boin_oc_multi'
print(
x,
digits = 1,
percent = FALSE,
kable = FALSE,
kable_format = "pipe",
...
)
Arguments
x |
An object of class |
digits |
Integer scalar. Number of decimal places. Defaults to 1. |
percent |
Logical scalar. Express the average number of patients and DLTs at each dose
as a percentage of the trial total instead of a count. Defaults to
|
kable |
Logical scalar. Return the table through |
kable_format |
Character scalar passed to |
... |
Further arguments, currently ignored. |
Value
The object x, invisibly.
Examples
oc <- sim_boin_multi(
target = 0.30,
scenarios = list(
list(name = "MTD at dose 3", p_true = c(0.05, 0.15, 0.30, 0.45, 0.60)),
list(name = "All toxic", p_true = c(0.35, 0.45, 0.55, 0.65, 0.75))
),
n_cohort = 10,
cohort_size = 3,
n_trials = 200,
seed = 123
)
print(oc)
print(oc, percent = TRUE)
Print Simulated BOIN Trials
Description
Show a compact summary of the object returned by boin_simulate
instead of printing the full trial matrices.
Usage
## S3 method for class 'boin_trials'
print(x, ...)
Arguments
x |
An object of class |
... |
Further arguments, currently ignored. |
Value
The object x, invisibly.
Examples
trials <- boin_simulate(
target = 0.30,
p_true = c(0.05, 0.15, 0.30, 0.45, 0.60),
n_cohort = 10,
cohort_size = 3,
n_trials = 100,
seed = 1
)
print(trials)
Print the Next Dose Combination of a BOIN Drug-Combination Trial
Description
Display the decision returned by comb_boin_next: the data at
the current combination, the boundaries that apply to it, the decision,
the candidates that were compared and the combinations eliminated so far.
Usage
## S3 method for class 'comb_boin_next'
print(x, ...)
Arguments
x |
An object of class |
... |
Further arguments, currently ignored. |
Value
The object x, invisibly.
Examples
n_pts <- matrix(c(3, 0, 0,
0, 0, 0), nrow = 2, byrow = TRUE)
n_tox <- matrix(0, nrow = 2, ncol = 3)
print(comb_boin_next(target = 0.30, n_pts = n_pts, n_tox = n_tox,
current = c(1, 1)))
Print Operating Characteristics of the BOIN Drug-Combination Design
Description
Display the summary produced by sim_comb_boin: the true DLT
rates, the selection percentages and the average numbers of patients and
DLTs at every dose combination, followed by the selection of the true MTD
and the exposure to combinations above the overdose cutoff.
Usage
## S3 method for class 'comb_boin_oc'
print(x, digits = 1, kable = FALSE, kable_format = "pipe", ...)
Arguments
x |
An object of class |
digits |
Integer scalar. Number of decimal places. Defaults to 1. |
kable |
Logical scalar. Return the table through |
kable_format |
Character scalar passed to |
... |
Further arguments, currently ignored. |
Value
The object x, invisibly.
Examples
p_true <- matrix(c(0.02, 0.04, 0.08, 0.14,
0.08, 0.25, 0.42, 0.48,
0.25, 0.45, 0.50, 0.60), nrow = 3, byrow = TRUE)
oc <- sim_comb_boin(
target = 0.25,
p_true = p_true,
n_cohort = 16,
cohort_size = 3,
n_trials = 200,
seed = 123
)
print(oc)
print(oc, digits = 2)
Print Operating Characteristics of the BOIN Drug-Combination Design Across Scenarios
Description
Display the table produced by sim_comb_boin_multi, one row per
scenario. The full results of a scenario are printed by printing its
element of x$results.
Usage
## S3 method for class 'comb_boin_oc_multi'
print(x, digits = 1, kable = FALSE, kable_format = "pipe", ...)
Arguments
x |
An object of class |
digits |
Integer scalar. Number of decimal places. Defaults to 1. |
kable |
Logical scalar. Return the table through |
kable_format |
Character scalar passed to |
... |
Further arguments, currently ignored. |
Value
The object x, invisibly.
Examples
oc <- sim_comb_boin_multi(
target = 0.30,
scenarios = list(
"MTD in the middle" = matrix(c(0.10, 0.20, 0.30,
0.20, 0.30, 0.45), 2, byrow = TRUE),
"All toxic" = matrix(c(0.40, 0.50, 0.60,
0.50, 0.60, 0.70), 2, byrow = TRUE)
),
n_cohort = 10,
cohort_size = 3,
n_trials = 200,
seed = 123
)
print(oc)
Print Simulated BOIN Drug-Combination Trials
Description
Show a compact summary of the object returned by
comb_boin_simulate instead of printing the full trial arrays.
Usage
## S3 method for class 'comb_boin_trials'
print(x, ...)
Arguments
x |
An object of class |
... |
Further arguments, currently ignored. |
Value
The object x, invisibly.
Examples
p_true <- matrix(c(0.05, 0.15, 0.30,
0.15, 0.30, 0.45), nrow = 2, byrow = TRUE)
trials <- comb_boin_simulate(
target = 0.30,
p_true = p_true,
n_cohort = 10,
cohort_size = 3,
n_trials = 100,
seed = 1
)
print(trials)
Print a 3+3 Decision Table
Description
Display the decision table produced by decision_table_3p3:
one row per number of patients and range of DLTs sharing a decision, for
dose escalation and, with mtd_rule = "expand", for the search for
the MTD, followed by what happens once escalation stops.
Usage
## S3 method for class 'decision_table_3p3'
print(x, ...)
Arguments
x |
An object of class |
... |
Further arguments, currently ignored. |
Details
A data frame that no longer has the columns or attributes of a decision table, for example after selecting columns, is printed as a plain data frame.
Value
The object x, invisibly.
See Also
decision_table_3p3,
plot.decision_table_3p3
Examples
print(decision_table_3p3())
print(decision_table_3p3(mtd_rule = "expand"))
Print Operating Characteristics of the 3+3 Design
Description
Display the summary table produced by oc_3p3 or
sim_3p3. The layout matches
print.boin_oc, so a 3+3 table can be read beside a BOIN one.
Usage
## S3 method for class 'oc_3p3'
print(
x,
digits = 1,
percent = FALSE,
kable = FALSE,
kable_format = "pipe",
...
)
Arguments
x |
An object of class |
digits |
Integer scalar. Number of decimal places. Defaults to 1. |
percent |
Logical scalar. Express the average number of patients and DLTs at each dose
as a percentage of the trial total instead of a count. Defaults to
|
kable |
Logical scalar. Return the table through |
kable_format |
Character scalar passed to |
... |
Further arguments, currently ignored. |
Value
The object x, invisibly.
See Also
Examples
oc <- oc_3p3(p_true = c(0.30, 0.48, 0.67))
print(oc)
print(oc, percent = TRUE)
Print a TITE-BOIN Decision Table
Description
Display the decision table produced by tite_boin_decision_table
in the layout of the published tables: one row per number of patients
treated, number of DLTs and range of pending patients sharing a decision,
with the boundaries on the follow-up statistic in the Escalate, Stay and
De-escalate columns.
Usage
## S3 method for class 'tite_boin_decision_table'
print(x, cohort_size = NULL, digits = 2, ...)
Arguments
x |
An object of class |
cohort_size |
Integer scalar or |
digits |
Integer scalar. Number of decimal places of the boundaries. Defaults to 2, as in the published tables. |
... |
Further arguments, currently ignored. |
Details
A boundary shown as ">= 2.15" under Escalate means that the dose is
escalated when the follow-up statistic is at least 2.15; the statistic is
STFT for method = "imputation" and ESS for method = "ess".
"Suspend if >= 4.23" under Escalate marks an escalation blocked by
min_completed. When the table was built with a positive
min_follow_up, an escalation with pending patients carries the
condition on MF, for example ">= 0.22 & MF >= 0.25"; accrual is
suspended when the condition on the follow-up statistic holds but the one
on MF does not.
A data frame that no longer has the columns or attributes of a decision table, for example after selecting columns, is printed as a plain data frame.
Value
The object x, invisibly.
See Also
tite_boin_decision_table,
plot.tite_boin_decision_table
Examples
decisions <- tite_boin_decision_table(target = 0.3, max_n = 15)
# Table S1 of Yuan et al. (2018)
print(decisions, cohort_size = 3)
# Boundaries with three decimal places
print(decisions[decisions$n == 9, ], digits = 3)
Print Operating Characteristics of a TITE-BOIN Design
Description
Display the summary produced by sim_tite_boin: the design,
the table of print.boin_oc, the exposure to doses above the
overdose cutoff, and the duration of the trials and the suspensions of
accrual.
Usage
## S3 method for class 'tite_boin_oc'
print(
x,
digits = 1,
percent = FALSE,
kable = FALSE,
kable_format = "pipe",
...
)
Arguments
x |
An object of class |
digits |
Integer scalar. Number of decimal places. Defaults to 1. |
percent |
Logical scalar. Express the average number of patients and DLTs at each dose
as a percentage of the trial total instead of a count. Defaults to
|
kable |
Logical scalar. Return the table through |
kable_format |
Character scalar passed to |
... |
Further arguments, currently ignored. |
Value
The object x, invisibly.
Examples
oc <- sim_tite_boin(
target = 0.30,
p_true = c(0.05, 0.15, 0.30, 0.45, 0.60),
n_cohort = 10,
cohort_size = 3,
window = 3,
accrual_rate = 2,
n_trials = 200,
seed = 123
)
print(oc)
print(oc, percent = TRUE)
Print Operating Characteristics of a TITE-BOIN Design Across Scenarios
Description
Display the table produced by sim_tite_boin_multi, one block
of rows per scenario.
Usage
## S3 method for class 'tite_boin_oc_multi'
print(
x,
digits = 1,
percent = FALSE,
kable = FALSE,
kable_format = "pipe",
...
)
Arguments
x |
An object of class |
digits |
Integer scalar. Number of decimal places. Defaults to 1. |
percent |
Logical scalar. Express the average number of patients and DLTs at each dose
as a percentage of the trial total instead of a count. Defaults to
|
kable |
Logical scalar. Return the table through |
kable_format |
Character scalar passed to |
... |
Further arguments, currently ignored. |
Value
The object x, invisibly.
Examples
scenarios <- list(
list(name = "MTD at dose 3", p_true = c(0.05, 0.15, 0.30, 0.45, 0.60)),
list(name = "All toxic", p_true = c(0.35, 0.45, 0.55, 0.65, 0.75))
)
oc <- sim_tite_boin_multi(
target = 0.30,
scenarios = scenarios,
n_cohort = 10,
cohort_size = 3,
window = 3,
accrual_rate = 2,
n_trials = 200,
seed = 123
)
print(oc)
print(oc, percent = TRUE)
Print Simulated TITE-BOIN Trials
Description
Show a compact summary of the object returned by
tite_boin_simulate instead of printing the full trial
matrices.
Usage
## S3 method for class 'tite_boin_trials'
print(x, ...)
Arguments
x |
An object of class |
... |
Further arguments, currently ignored. |
Value
The object x, invisibly.
Examples
trials <- tite_boin_simulate(
target = 0.30,
p_true = c(0.05, 0.15, 0.30, 0.45, 0.60),
n_cohort = 10,
cohort_size = 3,
window = 3,
accrual_rate = 2,
n_trials = 100,
seed = 1
)
print(trials)
Deprecated Functions in simFastBOIN
Description
These functions were renamed in version 2.0.0. They still work but issue a deprecation warning and will be removed in a future release. Their return values are those of the replacement functions, which differ from the return values of version 1.3.2, so calls should be updated rather than left in place.
Usage
get_boin_boundary(...)
get_boin_decision(...)
get_boin_stopping_boundaries(...)
get_pts_and_tox(...)
isotonic_regression(...)
select_mtd(...)
Arguments
... |
Arguments passed to the replacement function. Note that the replacements use different argument names and a different argument order, so only calls that name every argument will carry over unchanged. |
Value
The value of the corresponding replacement function.
Replacements
get_boin_boundary()use
boin_lambdafor the interval boundaries, orboin_boundaryfor the integer decision boundaries.get_boin_decision()use
boin_decision_table.get_boin_stopping_boundaries()use
boin_boundarywithextrasafe = TRUEand read theb_stopcomponent.get_pts_and_tox()use
boin_simulate.isotonic_regression()use
boin_isotonic.select_mtd()use
boin_select_mtd, which now takes the patient and DLT counts instead of precomputed isotonic estimates.
Simulate the 3+3 Design
Description
Simulate the traditional 3+3 dose-finding design and summarize the same
quantities that oc_3p3 computes exactly. The two are meant to
be used together: oc_3p3() gives the answer without Monte Carlo
error, and this function confirms it from independent trials.
Usage
sim_3p3(
p_true,
n_trials = 10000,
mtd_rule = c("previous", "expand"),
start_dose = 1,
overdose_cutoff = NULL,
seed = 123
)
Arguments
p_true |
Numeric vector. True DLT probability at each dose level, in increasing dose order. |
n_trials |
Integer scalar. Number of trials to simulate. Defaults to 10000. |
mtd_rule |
Character scalar, either |
start_dose |
Integer scalar. Dose level for the first cohort. Defaults to 1. |
overdose_cutoff |
Numeric scalar or |
seed |
Integer scalar or |
Details
The design is described under oc_3p3. Since the operating
characteristics of the 3+3 design can be written in closed form, this
function is a check on that closed form rather than the way to obtain the
numbers. Simulation is the only option when a quantity is wanted that the
closed form does not provide, such as the distribution of the sample size
rather than its mean.
Value
An object of class oc_3p3, with the components described in
oc_3p3. The method component is the number of trials
rather than "exact".
See Also
Examples
exact <- oc_3p3(p_true = c(0.30, 0.48, 0.67))
simulated <- sim_3p3(p_true = c(0.30, 0.48, 0.67), n_trials = 2000, seed = 1)
round(exact$sel_percent, 2)
round(simulated$sel_percent, 2)
Operating Characteristics of a BE-BOIN Design
Description
Simulate the BOIN design with backfilling and late-onset toxicity (BE-BOIN) of Chen et al. (2026) many times under one scenario of DLT and response probabilities, and summarize how often each dose is selected as the MTD, how many patients are treated and backfilled at each dose, how many DLTs and responses occur, and how long the trials last.
Usage
sim_be_boin(
target,
p_true,
p_resp,
n_cohort,
cohort_size,
window,
accrual_rate,
n_cap = 12,
backfill_dose = c("highest", "lowest"),
conflict_dose = c("lowest", "highest"),
no_slot = c("wait", "leave"),
accrual = c("exponential", "uniform", "fixed"),
dlt_time = c("weibull", "uniform"),
late_fraction = 0.5,
resp_window = window,
resp_late_fraction = 0.5,
resp_cor = 0,
max_pending_ratio = 0.49,
min_completed = 0,
min_follow_up = 0.25,
n_trials = 10000,
start_dose = 1,
n_earlystop = 18,
p_saf = NULL,
p_tox = NULL,
cutoff_eli = 0.95,
extrasafe = FALSE,
offset = 0.05,
bound_mtd = FALSE,
mtd_max_estimate = NULL,
min_mtd_sample = 1,
overdose_cutoff = NULL,
n_earlystop_rule = c("with_stay", "simple"),
keep_trials = FALSE,
verbose = FALSE,
seed = 123
)
Arguments
target |
Numeric scalar. Target DLT probability, for example 0.25. |
p_true |
Numeric vector. True DLT probability at each dose level, in increasing dose order. The probability of a DLT within the assessment window. |
p_resp |
Numeric vector of the same length as |
n_cohort |
Integer scalar. Number of cohorts in the dose escalation. |
cohort_size |
Integer scalar or vector. Number of patients per cohort of the dose
escalation. A scalar is used for every cohort. A vector shorter than
|
window |
Numeric scalar. Length of the DLT assessment window. |
accrual_rate |
Numeric scalar. Average number of patients arriving per unit of time, in the
same unit as |
n_cap |
Integer scalar. A dose is no longer backfilled once this many patients, from the dose escalation and from backfilling together, have been treated at it. The dose escalation can still treat patients at the dose. Defaults to 12. |
backfill_dose |
Character scalar. Which dose receives a backfill patient when several are
open: |
conflict_dose |
Character scalar. When the data of several backfilled doses conflict with
those of the current dose, which of them anchors the pooled estimate:
|
no_slot |
Character scalar. What happens to a patient who arrives when neither the
dose escalation nor any backfill dose can take a patient: |
accrual |
Character scalar. Distribution of the times between arrivals:
|
dlt_time |
Character scalar. Distribution of the time to DLT within the window, and of
the time to response within the response window: |
late_fraction |
Numeric scalar strictly between 0 and 1. Share of the DLTs that occur in the second half of the assessment window under the Weibull distribution. Defaults to 0.5. |
resp_window |
Numeric scalar. Length of the window within which a response is observed.
Defaults to |
resp_late_fraction |
Numeric scalar strictly between 0 and 1. Share of the responses that occur in the second half of the response window under the Weibull distribution. Defaults to 0.5. |
resp_cor |
Numeric scalar strictly between -1 and 1. Correlation of the Gaussian copula that links the DLT and the response of a patient; a positive value makes a response more likely in a patient with a DLT. Defaults to 0, independence. |
max_pending_ratio |
Numeric scalar greater than 0 and at most 1. Rule 1 of the design: the
escalation is suspended when the proportion of pending patients at the
current dose exceeds this value, unless the dose is de-escalated whatever
their outcomes. Defaults to 0.49, which suspends when fewer than 51 percent
have completed the assessment, as in Chen et al. (2026). See
|
min_completed |
Integer scalar. While some patients are pending, escalation requires at
least this many patients with a completed assessment. Defaults to 0, which
the design does not use. See |
min_follow_up |
Numeric scalar between 0 and 1. Rule 2 of the design: escalation requires
every pending patient at the current dose to have been followed for at
least this fraction of the window. Defaults to 0.25, as in Chen et al.
(2026). See |
n_trials |
Integer scalar. Number of trials to simulate. Defaults to 10000. |
start_dose |
Integer scalar. Dose level for the first cohort. Defaults to 1. |
n_earlystop |
Integer scalar. The trial stops once this many patients, backfilled ones included, have been treated at the current dose and the design would stay there. Defaults to 18. |
p_saf |
Numeric scalar. Highest DLT probability deemed subtherapeutic.
Defaults to |
p_tox |
Numeric scalar. Lowest DLT probability deemed overly toxic.
Defaults to |
cutoff_eli |
Numeric scalar. Posterior probability cutoff for dose elimination. Defaults to 0.95. |
extrasafe |
Logical scalar. Apply the stricter safety stopping rule at the lowest dose.
Defaults to |
offset |
Numeric scalar between 0 and 0.5. Amount by which |
bound_mtd |
Logical scalar. Require the isotonic estimate at the selected dose to be at
or below the de-escalation boundary. Defaults to |
mtd_max_estimate |
Numeric scalar or |
min_mtd_sample |
Integer scalar. Smallest number of patients a dose must have received to be eligible as the MTD. Defaults to 1. |
overdose_cutoff |
Numeric scalar or |
n_earlystop_rule |
Character scalar, either |
keep_trials |
Logical scalar. Keep the full trial by trial data in the result.
Defaults to |
verbose |
Logical scalar. Report progress while the simulation runs.
Defaults to |
seed |
Integer scalar or |
Details
The trials are simulated by be_boin_simulate, whose details
describe the conduct of a trial. The MTD is selected as in
sim_bf_boin.
When no dose is ever opened for backfilling, for example with every
p_resp equal to 0, and with no_slot = "wait", every result
that the two functions share agrees with that of
sim_tite_boin with method = "imputation", the same
suspension rules and the same seed.
Only the MTD is selected. The second stage of Chen et al. (2026), which randomizes patients between doses to choose the optimal biological dose, is not part of the simulation.
Value
An object of class c("be_boin_oc", "backfill_oc", "boin_oc"), with
the components described in sim_bf_boin.
References
Chen, K., Zhao, Y., Takeda, K. and Yuan, Y. (2026). BE-BOIN: A Dose Optimization Design Accommodating Backfill and Late-Onset Toxicity. Therapeutic Innovation and Regulatory Science. doi:10.1007/s43441-026-00994-0
See Also
be_boin_simulate, sim_be_boin_multi,
sim_bf_boin, sim_tite_boin
Examples
# A three month window with two patients a month
oc <- sim_be_boin(
target = 0.25,
p_true = c(0.04, 0.12, 0.25, 0.43, 0.63),
p_resp = c(0.10, 0.20, 0.30, 0.45, 0.58),
n_cohort = 10,
cohort_size = 3,
window = 3,
accrual_rate = 2,
n_earlystop = 9,
n_trials = 500,
seed = 123
)
oc
Operating Characteristics of a BE-BOIN Design Across Several Scenarios
Description
Run sim_be_boin under a list of scenarios of DLT and response
probabilities that share the same design, and collect the results into one
table.
Usage
sim_be_boin_multi(
target,
scenarios,
n_cohort,
cohort_size,
window,
accrual_rate,
n_cap = 12,
backfill_dose = c("highest", "lowest"),
conflict_dose = c("lowest", "highest"),
no_slot = c("wait", "leave"),
accrual = c("exponential", "uniform", "fixed"),
dlt_time = c("weibull", "uniform"),
late_fraction = 0.5,
resp_window = window,
resp_late_fraction = 0.5,
resp_cor = 0,
max_pending_ratio = 0.49,
min_completed = 0,
min_follow_up = 0.25,
n_trials = 10000,
start_dose = 1,
n_earlystop = 18,
p_saf = NULL,
p_tox = NULL,
cutoff_eli = 0.95,
extrasafe = FALSE,
offset = 0.05,
bound_mtd = FALSE,
mtd_max_estimate = NULL,
min_mtd_sample = 1,
overdose_cutoff = NULL,
n_earlystop_rule = c("with_stay", "simple"),
keep_trials = FALSE,
verbose = FALSE,
seed = 123
)
Arguments
target |
Numeric scalar. Target DLT probability, for example 0.25. |
scenarios |
A list of scenarios. Each element is a list with a |
n_cohort |
Integer scalar. Number of cohorts in the dose escalation. |
cohort_size |
Integer scalar or vector. Number of patients per cohort of the dose
escalation. A scalar is used for every cohort. A vector shorter than
|
window |
Numeric scalar. Length of the DLT assessment window. |
accrual_rate |
Numeric scalar. Average number of patients arriving per unit of time, in the
same unit as |
n_cap |
Integer scalar. A dose is no longer backfilled once this many patients, from the dose escalation and from backfilling together, have been treated at it. The dose escalation can still treat patients at the dose. Defaults to 12. |
backfill_dose |
Character scalar. Which dose receives a backfill patient when several are
open: |
conflict_dose |
Character scalar. When the data of several backfilled doses conflict with
those of the current dose, which of them anchors the pooled estimate:
|
no_slot |
Character scalar. What happens to a patient who arrives when neither the
dose escalation nor any backfill dose can take a patient: |
accrual |
Character scalar. Distribution of the times between arrivals:
|
dlt_time |
Character scalar. Distribution of the time to DLT within the window, and of
the time to response within the response window: |
late_fraction |
Numeric scalar strictly between 0 and 1. Share of the DLTs that occur in the second half of the assessment window under the Weibull distribution. Defaults to 0.5. |
resp_window |
Numeric scalar. Length of the window within which a response is observed.
Defaults to |
resp_late_fraction |
Numeric scalar strictly between 0 and 1. Share of the responses that occur in the second half of the response window under the Weibull distribution. Defaults to 0.5. |
resp_cor |
Numeric scalar strictly between -1 and 1. Correlation of the Gaussian copula that links the DLT and the response of a patient; a positive value makes a response more likely in a patient with a DLT. Defaults to 0, independence. |
max_pending_ratio |
Numeric scalar greater than 0 and at most 1. Rule 1 of the design: the
escalation is suspended when the proportion of pending patients at the
current dose exceeds this value, unless the dose is de-escalated whatever
their outcomes. Defaults to 0.49, which suspends when fewer than 51 percent
have completed the assessment, as in Chen et al. (2026). See
|
min_completed |
Integer scalar. While some patients are pending, escalation requires at
least this many patients with a completed assessment. Defaults to 0, which
the design does not use. See |
min_follow_up |
Numeric scalar between 0 and 1. Rule 2 of the design: escalation requires
every pending patient at the current dose to have been followed for at
least this fraction of the window. Defaults to 0.25, as in Chen et al.
(2026). See |
n_trials |
Integer scalar. Number of trials to simulate. Defaults to 10000. |
start_dose |
Integer scalar. Dose level for the first cohort. Defaults to 1. |
n_earlystop |
Integer scalar. The trial stops once this many patients, backfilled ones included, have been treated at the current dose and the design would stay there. Defaults to 18. |
p_saf |
Numeric scalar. Highest DLT probability deemed subtherapeutic.
Defaults to |
p_tox |
Numeric scalar. Lowest DLT probability deemed overly toxic.
Defaults to |
cutoff_eli |
Numeric scalar. Posterior probability cutoff for dose elimination. Defaults to 0.95. |
extrasafe |
Logical scalar. Apply the stricter safety stopping rule at the lowest dose.
Defaults to |
offset |
Numeric scalar between 0 and 0.5. Amount by which |
bound_mtd |
Logical scalar. Require the isotonic estimate at the selected dose to be at
or below the de-escalation boundary. Defaults to |
mtd_max_estimate |
Numeric scalar or |
min_mtd_sample |
Integer scalar. Smallest number of patients a dose must have received to be eligible as the MTD. Defaults to 1. |
overdose_cutoff |
Numeric scalar or |
n_earlystop_rule |
Character scalar, either |
keep_trials |
Logical scalar. Keep the full trial by trial data in the result.
Defaults to |
verbose |
Logical scalar. Report progress while the simulation runs.
Defaults to |
seed |
Integer scalar or |
Value
An object of class c("be_boin_oc_multi", "backfill_oc_multi",
"boin_oc_multi"), with the components described in
sim_bf_boin_multi; results holds be_boin_oc
objects.
See Also
sim_be_boin, sim_bf_boin_multi
Examples
scenarios <- list(
list(name = "MTD at dose 3", p_true = c(0.04, 0.12, 0.25, 0.43, 0.63),
p_resp = c(0.10, 0.20, 0.30, 0.45, 0.58)),
list(name = "Plateau", p_true = c(0.04, 0.12, 0.25, 0.43, 0.63),
p_resp = c(0.30, 0.32, 0.35, 0.36, 0.36))
)
oc <- sim_be_boin_multi(
target = 0.25,
scenarios = scenarios,
n_cohort = 10,
cohort_size = 3,
window = 3,
accrual_rate = 2,
n_earlystop = 9,
n_trials = 200,
seed = 123
)
oc
Operating Characteristics of a BF-BOIN Design
Description
Simulate the BOIN design with backfilling (BF-BOIN) of Zhao et al. (2024) many times under one scenario of DLT and response probabilities, and summarize how often each dose is selected as the MTD, how many patients are treated and backfilled at each dose, how many DLTs and responses occur, and how long the trials last.
Usage
sim_bf_boin(
target,
p_true,
p_resp,
n_cohort,
cohort_size,
window,
accrual_rate,
n_cap = 12,
backfill_dose = c("highest", "lowest"),
conflict_dose = c("highest", "lowest"),
no_slot = c("wait", "leave"),
accrual = c("exponential", "uniform", "fixed"),
dlt_time = c("weibull", "uniform"),
late_fraction = 0.5,
resp_window = window,
resp_late_fraction = 0.5,
resp_cor = 0,
n_trials = 10000,
start_dose = 1,
n_earlystop = 18,
p_saf = NULL,
p_tox = NULL,
cutoff_eli = 0.95,
extrasafe = FALSE,
offset = 0.05,
stay_on_1_of_3 = FALSE,
bound_mtd = FALSE,
mtd_max_estimate = NULL,
min_mtd_sample = 1,
overdose_cutoff = NULL,
n_earlystop_rule = c("with_stay", "simple"),
keep_trials = FALSE,
verbose = FALSE,
seed = 123
)
Arguments
target |
Numeric scalar. Target DLT probability, for example 0.25. |
p_true |
Numeric vector. True DLT probability at each dose level, in increasing dose order. The probability of a DLT within the assessment window. |
p_resp |
Numeric vector of the same length as |
n_cohort |
Integer scalar. Number of cohorts in the dose escalation. |
cohort_size |
Integer scalar or vector. Number of patients per cohort of the dose
escalation. A scalar is used for every cohort. A vector shorter than
|
window |
Numeric scalar. Length of the DLT assessment window. |
accrual_rate |
Numeric scalar. Average number of patients arriving per unit of time, in the
same unit as |
n_cap |
Integer scalar. A dose is no longer backfilled once this many patients, from the dose escalation and from backfilling together, have been treated at it. The dose escalation can still treat patients at the dose. Defaults to 12. |
backfill_dose |
Character scalar. Which dose receives a backfill patient when several are
open: |
conflict_dose |
Character scalar. When the data of several backfilled doses conflict with
those of the current dose, which of them anchors the pooled estimate:
|
no_slot |
Character scalar. What happens to a patient who arrives when neither the
dose escalation nor any backfill dose can take a patient: |
accrual |
Character scalar. Distribution of the times between arrivals:
|
dlt_time |
Character scalar. Distribution of the time to DLT within the window, and of
the time to response within the response window: |
late_fraction |
Numeric scalar strictly between 0 and 1. Share of the DLTs that occur in the second half of the assessment window under the Weibull distribution. Defaults to 0.5. |
resp_window |
Numeric scalar. Length of the window within which a response is observed.
Defaults to |
resp_late_fraction |
Numeric scalar strictly between 0 and 1. Share of the responses that occur in the second half of the response window under the Weibull distribution. Defaults to 0.5. |
resp_cor |
Numeric scalar strictly between -1 and 1. Correlation of the Gaussian copula that links the DLT and the response of a patient; a positive value makes a response more likely in a patient with a DLT. Defaults to 0, independence. |
n_trials |
Integer scalar. Number of trials to simulate. Defaults to 10000. |
start_dose |
Integer scalar. Dose level for the first cohort. Defaults to 1. |
n_earlystop |
Integer scalar. The trial stops once this many patients, backfilled ones included, have been treated at the current dose and the design would stay there. Defaults to 18. |
p_saf |
Numeric scalar. Highest DLT probability deemed subtherapeutic.
Defaults to |
p_tox |
Numeric scalar. Lowest DLT probability deemed overly toxic.
Defaults to |
cutoff_eli |
Numeric scalar. Posterior probability cutoff for dose elimination. Defaults to 0.95. |
extrasafe |
Logical scalar. Apply the stricter safety stopping rule at the lowest dose.
Defaults to |
offset |
Numeric scalar between 0 and 0.5. Amount by which |
stay_on_1_of_3 |
Logical scalar. When |
bound_mtd |
Logical scalar. Require the isotonic estimate at the selected dose to be at
or below the de-escalation boundary. Defaults to |
mtd_max_estimate |
Numeric scalar or |
min_mtd_sample |
Integer scalar. Smallest number of patients a dose must have received to be eligible as the MTD. Defaults to 1. |
overdose_cutoff |
Numeric scalar or |
n_earlystop_rule |
Character scalar, either |
keep_trials |
Logical scalar. Keep the full trial by trial data in the result.
Defaults to |
verbose |
Logical scalar. Report progress while the simulation runs.
Defaults to |
seed |
Integer scalar or |
Details
The trials are simulated by bf_boin_simulate, whose details
describe the conduct of a trial. Once every patient has completed the
assessment the MTD is selected from the data of all patients, backfilled
ones included, exactly as in sim_boin, and a trial stopped for
safety selects no dose. The overdose cutoffs of 60 and 80 percent refer to
the size of the dose escalation, n_cohort cohorts.
When no dose is ever opened for backfilling, for example with every
p_resp equal to 0, the selection and the patient counts agree with
those of sim_boin under the same seed.
To reproduce Table 4 of Zhao et al. (2024), use target = 0.25,
n_cohort = 10, cohort_size = 3, window = 1,
accrual_rate = 3, n_earlystop = 9,
stay_on_1_of_3 = TRUE, accrual = "uniform" and
no_slot = "leave".
Value
An object of class c("bf_boin_oc", "backfill_oc", "boin_oc"), which
has every component of the result of sim_boin, so that code
written for sim_boin() also reads it, counting backfilled patients
among the patients treated, and in addition
n_bf_dose |
Average number of backfilled patients at each dose. |
total_n_bf |
Average number of backfilled patients per trial. |
pct_trials_backfill |
Percentage of trials with at least one backfilled patient. |
n_resp_dose |
Average number of patients with a response at each dose. |
total_n_resp |
Average number of patients with a response per trial. |
duration_mean |
Average trial duration, from the first arrival until
every enrolled patient has completed the DLT assessment, in the time unit
of |
duration_sd |
Standard deviation of the trial duration. |
pct_trials_suspended |
Percentage of trials in which the dose escalation had to wait at least once. |
avg_n_suspensions |
Average number of decisions per trial at which the dose escalation had to wait. |
avg_time_suspended |
Average total time per trial during which the dose escalation waited. |
avg_n_turned_away |
Average number of patients turned away per trial,
which is zero unless |
p_resp |
The true response probabilities. |
The trials component, when kept, holds the trial by trial data of
bf_boin_simulate together with the selected MTD.
References
Zhao, Y., Yuan, Y., Korn, E. L. and Freidlin, B. (2024). Backfilling Patients in Phase I Dose-Escalation Trials Using Bayesian Optimal Interval Design (BOIN). Clinical Cancer Research, 30(4), 673-679.
See Also
bf_boin_simulate, sim_bf_boin_multi,
sim_be_boin, sim_boin
Examples
# Scenario 3 of Zhao et al. (2024)
oc <- sim_bf_boin(
target = 0.25,
p_true = c(0.04, 0.12, 0.25, 0.43, 0.63),
p_resp = c(0.10, 0.20, 0.30, 0.45, 0.58),
n_cohort = 10,
cohort_size = 3,
window = 1,
accrual_rate = 3,
n_earlystop = 9,
stay_on_1_of_3 = TRUE,
accrual = "uniform",
no_slot = "leave",
n_trials = 500,
seed = 123
)
oc
Operating Characteristics of a BF-BOIN Design Across Several Scenarios
Description
Run sim_bf_boin under a list of scenarios of DLT and response
probabilities that share the same design, and collect the results into one
table.
Usage
sim_bf_boin_multi(
target,
scenarios,
n_cohort,
cohort_size,
window,
accrual_rate,
n_cap = 12,
backfill_dose = c("highest", "lowest"),
conflict_dose = c("highest", "lowest"),
no_slot = c("wait", "leave"),
accrual = c("exponential", "uniform", "fixed"),
dlt_time = c("weibull", "uniform"),
late_fraction = 0.5,
resp_window = window,
resp_late_fraction = 0.5,
resp_cor = 0,
n_trials = 10000,
start_dose = 1,
n_earlystop = 18,
p_saf = NULL,
p_tox = NULL,
cutoff_eli = 0.95,
extrasafe = FALSE,
offset = 0.05,
stay_on_1_of_3 = FALSE,
bound_mtd = FALSE,
mtd_max_estimate = NULL,
min_mtd_sample = 1,
overdose_cutoff = NULL,
n_earlystop_rule = c("with_stay", "simple"),
keep_trials = FALSE,
verbose = FALSE,
seed = 123
)
Arguments
target |
Numeric scalar. Target DLT probability, for example 0.25. |
scenarios |
A list of scenarios. Each element is a list with a |
n_cohort |
Integer scalar. Number of cohorts in the dose escalation. |
cohort_size |
Integer scalar or vector. Number of patients per cohort of the dose
escalation. A scalar is used for every cohort. A vector shorter than
|
window |
Numeric scalar. Length of the DLT assessment window. |
accrual_rate |
Numeric scalar. Average number of patients arriving per unit of time, in the
same unit as |
n_cap |
Integer scalar. A dose is no longer backfilled once this many patients, from the dose escalation and from backfilling together, have been treated at it. The dose escalation can still treat patients at the dose. Defaults to 12. |
backfill_dose |
Character scalar. Which dose receives a backfill patient when several are
open: |
conflict_dose |
Character scalar. When the data of several backfilled doses conflict with
those of the current dose, which of them anchors the pooled estimate:
|
no_slot |
Character scalar. What happens to a patient who arrives when neither the
dose escalation nor any backfill dose can take a patient: |
accrual |
Character scalar. Distribution of the times between arrivals:
|
dlt_time |
Character scalar. Distribution of the time to DLT within the window, and of
the time to response within the response window: |
late_fraction |
Numeric scalar strictly between 0 and 1. Share of the DLTs that occur in the second half of the assessment window under the Weibull distribution. Defaults to 0.5. |
resp_window |
Numeric scalar. Length of the window within which a response is observed.
Defaults to |
resp_late_fraction |
Numeric scalar strictly between 0 and 1. Share of the responses that occur in the second half of the response window under the Weibull distribution. Defaults to 0.5. |
resp_cor |
Numeric scalar strictly between -1 and 1. Correlation of the Gaussian copula that links the DLT and the response of a patient; a positive value makes a response more likely in a patient with a DLT. Defaults to 0, independence. |
n_trials |
Integer scalar. Number of trials to simulate. Defaults to 10000. |
start_dose |
Integer scalar. Dose level for the first cohort. Defaults to 1. |
n_earlystop |
Integer scalar. The trial stops once this many patients, backfilled ones included, have been treated at the current dose and the design would stay there. Defaults to 18. |
p_saf |
Numeric scalar. Highest DLT probability deemed subtherapeutic.
Defaults to |
p_tox |
Numeric scalar. Lowest DLT probability deemed overly toxic.
Defaults to |
cutoff_eli |
Numeric scalar. Posterior probability cutoff for dose elimination. Defaults to 0.95. |
extrasafe |
Logical scalar. Apply the stricter safety stopping rule at the lowest dose.
Defaults to |
offset |
Numeric scalar between 0 and 0.5. Amount by which |
stay_on_1_of_3 |
Logical scalar. When |
bound_mtd |
Logical scalar. Require the isotonic estimate at the selected dose to be at
or below the de-escalation boundary. Defaults to |
mtd_max_estimate |
Numeric scalar or |
min_mtd_sample |
Integer scalar. Smallest number of patients a dose must have received to be eligible as the MTD. Defaults to 1. |
overdose_cutoff |
Numeric scalar or |
n_earlystop_rule |
Character scalar, either |
keep_trials |
Logical scalar. Keep the trial by trial data of every scenario.
Defaults to |
verbose |
Logical scalar. Report progress while the simulations run.
Defaults to |
seed |
Integer scalar or |
Value
An object of class c("bf_boin_oc_multi", "backfill_oc_multi",
"boin_oc_multi"), which is a list with components
results |
Named list of |
summary_table |
Data frame collecting all scenarios, with seven rows per scenario: the true DLT and response rates, the MTD selection, the patients treated, the backfilled patients, the patients with DLT and the average trial duration. |
scenario_names |
Character vector of scenario names. |
n_doses |
Number of dose levels. |
call |
The matched call. |
See Also
sim_bf_boin, sim_be_boin_multi
Examples
# Scenarios 2 and 6 of Zhao et al. (2024)
scenarios <- list(
list(name = "Scenario 2", p_true = c(0.12, 0.25, 0.42, 0.49, 0.55),
p_resp = c(0.20, 0.30, 0.40, 0.50, 0.60)),
list(name = "Scenario 6", p_true = c(0.12, 0.25, 0.42, 0.49, 0.55),
p_resp = c(0.30, 0.35, 0.36, 0.36, 0.36))
)
oc <- sim_bf_boin_multi(
target = 0.25,
scenarios = scenarios,
n_cohort = 10,
cohort_size = 3,
window = 1,
accrual_rate = 3,
n_earlystop = 9,
stay_on_1_of_3 = TRUE,
n_trials = 200,
seed = 123
)
oc
Operating Characteristics of a BOIN Design
Description
Simulate a BOIN dose-finding trial many times under one dose-toxicity scenario and summarize how often each dose is selected as the MTD, how many patients are treated at each dose and how many DLTs are observed.
Usage
sim_boin(
target,
p_true,
n_cohort,
cohort_size,
n_trials = 10000,
start_dose = 1,
n_earlystop = 18,
p_saf = NULL,
p_tox = NULL,
cutoff_eli = 0.95,
extrasafe = FALSE,
offset = 0.05,
titration = FALSE,
stay_on_1_of_3 = FALSE,
bound_mtd = FALSE,
mtd_max_estimate = NULL,
min_mtd_sample = 1,
overdose_cutoff = NULL,
n_earlystop_rule = c("with_stay", "simple"),
keep_trials = FALSE,
verbose = FALSE,
seed = 123
)
Arguments
target |
Numeric scalar. Target DLT probability, for example 0.30. |
p_true |
Numeric vector. True DLT probability at each dose level, in increasing dose order. |
n_cohort |
Integer scalar. Number of cohorts in a trial. |
cohort_size |
Integer scalar or vector. Number of patients per cohort. A scalar is used for
every cohort. A vector shorter than |
n_trials |
Integer scalar. Number of trials to simulate. Defaults to 10000. |
start_dose |
Integer scalar. Dose level for the first cohort. Defaults to 1. It is
ignored when |
n_earlystop |
Integer scalar. The trial stops once this many patients have been treated at the current dose and the design would stay there. Defaults to 18. Set it to a value above the maximum sample size to switch this rule off. |
p_saf |
Numeric scalar. Highest DLT probability deemed subtherapeutic.
Defaults to |
p_tox |
Numeric scalar. Lowest DLT probability deemed overly toxic.
Defaults to |
cutoff_eli |
Numeric scalar. Posterior probability cutoff for dose elimination. Defaults to 0.95. |
extrasafe |
Logical scalar. Apply the stricter safety stopping rule at the lowest dose.
Defaults to |
offset |
Numeric scalar between 0 and 0.5. Amount by which |
titration |
Logical scalar. Start with single patient cohorts until the first DLT is
seen. Ignored when the first cohort size is one. Defaults to |
stay_on_1_of_3 |
Logical scalar. When |
bound_mtd |
Logical scalar. Require the isotonic estimate at the selected dose to be at
or below the de-escalation boundary. Defaults to |
mtd_max_estimate |
Numeric scalar or |
min_mtd_sample |
Integer scalar. Smallest number of patients a dose must have received to be eligible as the MTD. Defaults to 1. |
overdose_cutoff |
Numeric scalar or |
n_earlystop_rule |
Character scalar, either |
keep_trials |
Logical scalar. Keep the full trial by trial data in the result.
Defaults to |
verbose |
Logical scalar. Report progress while the simulation runs.
Defaults to |
seed |
Integer scalar or |
Details
The engine draws one uniform variate per patient, in enrollment order, and
applies the decision rules in the order used by BOIN::get.oc(). See
boin_simulate for the two places where a variate is drawn but
not used. With the same seed and matching arguments the two implementations
agree trial by trial, not merely on average.
Note that n_earlystop defaults to 18 here, whereas the reference
implementation defaults to 100, which in practice switches the rule off.
Value
An object of class boin_oc, which is a list with components
sel_percent |
Percentage of trials selecting each dose as the MTD. |
percent_no_mtd |
Percentage of trials ending without an MTD. |
n_pts_dose |
Average number of patients treated at each dose. |
n_tox_dose |
Average number of DLTs observed at each dose. |
total_n_pts |
Average total number of patients per trial. |
total_n_tox |
Average total number of DLTs per trial. |
overdose |
List describing the design's relationship with doses above |
stop_reason_percent |
Percentage of trials by reason for stopping. |
trials |
Trial level data when |
together with the design parameters and the call.
References
Liu S. and Yuan, Y. (2015). Bayesian Optimal Interval Designs for Phase I Clinical Trials. Journal of the Royal Statistical Society: Series C, 64, 507-523.
See Also
Examples
oc <- sim_boin(
target = 0.30,
p_true = c(0.05, 0.15, 0.30, 0.45, 0.60),
n_cohort = 10,
cohort_size = 3,
n_trials = 500,
seed = 123
)
oc
# A larger run with the safety options switched on
oc_safe <- sim_boin(
target = 0.30,
p_true = c(0.30, 0.40, 0.50, 0.60, 0.70),
n_cohort = 20,
cohort_size = 3,
n_trials = 10000,
extrasafe = TRUE,
bound_mtd = TRUE,
titration = TRUE,
seed = 123
)
oc_safe
# How often are patients dosed above a true DLT rate of 0.33?
oc_cut <- sim_boin(
target = 0.30,
p_true = c(0.10, 0.20, 0.30, 0.42, 0.55),
n_cohort = 20,
cohort_size = 3,
n_trials = 10000,
overdose_cutoff = 0.33,
seed = 123
)
oc_cut$overdose$pct_patients # patients dosed above 0.33
oc_cut$overdose$pct_trials_mtd_above # trials recommending a dose above 0.33
Operating Characteristics Across Several Scenarios
Description
Run sim_boin under a list of dose-toxicity scenarios that share
the same design, and collect the results into one table.
Usage
sim_boin_multi(
target,
scenarios,
n_cohort,
cohort_size,
n_trials = 10000,
start_dose = 1,
n_earlystop = 18,
p_saf = NULL,
p_tox = NULL,
cutoff_eli = 0.95,
extrasafe = FALSE,
offset = 0.05,
titration = FALSE,
stay_on_1_of_3 = FALSE,
bound_mtd = FALSE,
mtd_max_estimate = NULL,
min_mtd_sample = 1,
overdose_cutoff = NULL,
n_earlystop_rule = c("with_stay", "simple"),
keep_trials = FALSE,
verbose = FALSE,
seed = 123
)
Arguments
target |
Numeric scalar. Target DLT probability. |
scenarios |
A list of scenarios. Each element is a list with a |
n_cohort |
Integer scalar. Number of cohorts in a trial. |
cohort_size |
Integer scalar or vector. Number of patients per cohort. |
n_trials |
Integer scalar. Number of trials per scenario. Defaults to 10000. |
start_dose |
Integer scalar. Dose level for the first cohort. Defaults to 1. It is
ignored when |
n_earlystop |
Integer scalar. Early stopping sample size at the current dose. Defaults to 18. |
p_saf |
Numeric scalar. Highest DLT probability deemed subtherapeutic.
Defaults to |
p_tox |
Numeric scalar. Lowest DLT probability deemed overly toxic.
Defaults to |
cutoff_eli |
Numeric scalar. Posterior probability cutoff for dose elimination. Defaults to 0.95. |
extrasafe |
Logical scalar. Apply the stricter safety stopping rule at the lowest dose. |
offset |
Numeric scalar between 0 and 0.5. Relaxation of |
titration |
Logical scalar. Start with single patient cohorts until the first DLT. |
stay_on_1_of_3 |
Logical scalar. Make one DLT out of three patients a stay rather than a
de-escalation. See |
bound_mtd |
Logical scalar. Bound the isotonic estimate at the selected MTD by the de-escalation boundary. |
mtd_max_estimate |
Numeric scalar or |
min_mtd_sample |
Integer scalar. Smallest number of patients for a dose to be eligible. |
overdose_cutoff |
Numeric scalar or |
n_earlystop_rule |
Character scalar, either |
keep_trials |
Logical scalar. Keep the trial by trial data of every scenario. |
verbose |
Logical scalar. Report progress while the simulations run. |
seed |
Integer scalar or |
Value
An object of class boin_oc_multi, which is a list with components
results |
Named list of |
summary_table |
Data frame collecting all scenarios. |
scenario_names |
Character vector of scenario names. |
n_doses |
Number of dose levels. |
call |
The matched call. |
See Also
Examples
scenarios <- list(
list(name = "MTD at dose 3", p_true = c(0.05, 0.15, 0.30, 0.45, 0.60)),
list(name = "All toxic", p_true = c(0.35, 0.45, 0.55, 0.65, 0.75))
)
oc <- sim_boin_multi(
target = 0.30,
scenarios = scenarios,
n_cohort = 10,
cohort_size = 3,
n_trials = 200,
seed = 123
)
oc
Operating Characteristics of the BOIN Drug-Combination Design
Description
Simulate a trial of two drugs given together, run with the BOIN drug-combination design of Lin and Yin (2017), many times under one matrix of true DLT probabilities, and summarize how often each dose combination is selected as the MTD, how many patients are treated at each combination and how many DLTs are observed.
Usage
sim_comb_boin(
target,
p_true,
n_cohort,
cohort_size,
n_trials = 10000,
start_dose = c(1, 1),
n_earlystop = 18,
p_saf = NULL,
p_tox = NULL,
cutoff_eli = 0.95,
extrasafe = FALSE,
offset = 0.05,
titration = FALSE,
bound_mtd = FALSE,
overdose_cutoff = NULL,
keep_trials = FALSE,
verbose = FALSE,
seed = 123
)
Arguments
target |
Numeric scalar. Target DLT probability, for example 0.30. |
p_true |
Numeric matrix. True DLT probability of each dose combination, with one row per dose level of drug A and one column per dose level of drug B, both in increasing dose order. |
n_cohort |
Integer scalar. Number of cohorts in a trial. |
cohort_size |
Integer scalar or vector. Number of patients per cohort. A scalar is used for
every cohort. A vector shorter than |
n_trials |
Integer scalar. Number of trials to simulate. Defaults to 10000. |
start_dose |
Integer vector of length two. Dose levels of drug A and drug B for the first
cohort. Defaults to |
n_earlystop |
Integer scalar. The trial stops once this many patients have been treated at the current combination and the design would neither escalate nor de-escalate, or cannot. Defaults to 18. Set it to a value above the maximum sample size to switch this rule off. |
p_saf |
Numeric scalar. Highest DLT probability deemed subtherapeutic.
Defaults to |
p_tox |
Numeric scalar. Lowest DLT probability deemed overly toxic.
Defaults to |
cutoff_eli |
Numeric scalar. Posterior probability cutoff for eliminating a combination. Defaults to 0.95. |
extrasafe |
Logical scalar. Apply the stricter safety stopping rule at the lowest
combination. Defaults to |
offset |
Numeric scalar between 0 and 0.5. Amount by which |
titration |
Logical scalar. Treat one patient per combination, moving up one level of
either drug, until the first DLT. Ignored when the first cohort size is one.
Defaults to |
bound_mtd |
Logical scalar. Require the isotonic estimate at the selected combination
to be below the de-escalation boundary. Defaults to |
overdose_cutoff |
Numeric scalar or |
keep_trials |
Logical scalar. Keep the full trial by trial data in the result.
Defaults to |
verbose |
Logical scalar. Report progress while the simulation runs.
Defaults to |
seed |
Integer scalar or |
Details
The trials are simulated with comb_boin_simulate and the MTD
is selected with comb_boin_select_mtd. A trial stopped for
safety at the lowest combination selects none. Both follow
BOIN::get.oc.comb() with mtd.contour = FALSE: with the same
seed and matching arguments the two implementations agree trial by trial.
pct_true_mtd_selected and pct_patients_true_mtd are the
quantities that the reference implementation reports as the selection
percentage of the MTD and the percentage of patients treated at the MTD.
Note that n_earlystop defaults to 18 here, whereas the reference
implementation defaults to 100, which in practice switches the rule off.
Only the design that searches for a single MTD combination is provided; the waterfall design of Zhang and Yuan (2016), which searches for the MTD contour, is not.
Value
An object of class comb_boin_oc, which is a list with components
sel_percent |
Matrix of the percentage of trials selecting each combination as the MTD. |
percent_no_mtd |
Percentage of trials ending without an MTD. |
n_pts_dose |
Matrix of the average number of patients treated at each combination. |
n_tox_dose |
Matrix of the average number of DLTs observed at each combination. |
total_n_pts |
Average total number of patients per trial. |
total_n_tox |
Average total number of DLTs per trial. |
true_mtd |
Two-column matrix of the dose levels of drug A and drug B of the combinations whose true DLT probability is closest to |
pct_true_mtd_selected |
Percentage of trials selecting one of these combinations. |
pct_patients_true_mtd |
Percentage of all patients treated at one of them. |
overdose |
List describing the exposure to combinations above |
stop_reason_percent |
Percentage of trials by reason for stopping. |
trials |
Trial level data when |
together with the design parameters and the call.
References
Lin, R. and Yin, G. (2017). Bayesian Optimal Interval Design for Dose Finding in Drug-Combination Trials. Statistical Methods in Medical Research, 26(5), 2155-2167.
Yan, F., Zhang, L., Zhou, Y., Pan, H., Liu, S. and Yuan, Y. (2020). BOIN: An R Package for Designing Single-Agent and Drug-Combination Dose-Finding Trials Using Bayesian Optimal Interval Designs. Journal of Statistical Software, 94(13), 1-32.
Zhang, L. and Yuan, Y. (2016). A Practical Bayesian Design to Identify the Maximum Tolerated Dose Contour for Drug Combination Trials. Statistics in Medicine, 35(27), 4924-4936.
See Also
sim_comb_boin_multi, comb_boin_simulate,
comb_boin_select_mtd
Examples
# The example of Yan and colleagues (2020): three levels of drug A, four of
# drug B and a target DLT rate of 0.25
p_true <- matrix(c(0.02, 0.04, 0.08, 0.14,
0.08, 0.25, 0.42, 0.48,
0.25, 0.45, 0.50, 0.60), nrow = 3, byrow = TRUE)
oc <- sim_comb_boin(
target = 0.25,
p_true = p_true,
n_cohort = 16,
cohort_size = 3,
n_trials = 500,
seed = 123
)
oc
# The settings of the article, which turn early stopping off
oc_jss <- sim_comb_boin(
target = 0.25,
p_true = p_true,
n_cohort = 16,
cohort_size = 3,
n_earlystop = 100,
n_trials = 1000,
seed = 6
)
oc_jss$pct_true_mtd_selected
Operating Characteristics of the BOIN Drug-Combination Design Across Scenarios
Description
Run sim_comb_boin under a list of matrices of true DLT
probabilities that share the same design, and collect the main results into
one table.
Usage
sim_comb_boin_multi(
target,
scenarios,
n_cohort,
cohort_size,
n_trials = 10000,
start_dose = c(1, 1),
n_earlystop = 18,
p_saf = NULL,
p_tox = NULL,
cutoff_eli = 0.95,
extrasafe = FALSE,
offset = 0.05,
titration = FALSE,
bound_mtd = FALSE,
overdose_cutoff = NULL,
keep_trials = FALSE,
verbose = FALSE,
seed = 123
)
Arguments
target |
Numeric scalar. Target DLT probability. |
scenarios |
A list of scenarios. Each element is a list with a |
n_cohort |
Integer scalar. Number of cohorts in a trial. |
cohort_size |
Integer scalar or vector. Number of patients per cohort. |
n_trials |
Integer scalar. Number of trials per scenario. Defaults to 10000. |
start_dose |
Integer vector of length two. Dose levels of drug A and drug B for the first
cohort. Defaults to |
n_earlystop |
Integer scalar. Early stopping sample size at the current combination. Defaults to 18. |
p_saf |
Numeric scalar. Highest DLT probability deemed subtherapeutic.
Defaults to |
p_tox |
Numeric scalar. Lowest DLT probability deemed overly toxic.
Defaults to |
cutoff_eli |
Numeric scalar. Posterior probability cutoff for eliminating a combination. Defaults to 0.95. |
extrasafe |
Logical scalar. Apply the stricter safety stopping rule at the lowest combination. |
offset |
Numeric scalar between 0 and 0.5. Relaxation of |
titration |
Logical scalar. Treat one patient per combination until the first DLT. |
bound_mtd |
Logical scalar. Require the isotonic estimate at the selected combination to be below the de-escalation boundary. |
overdose_cutoff |
Numeric scalar or |
keep_trials |
Logical scalar. Keep the trial by trial data of every scenario. |
verbose |
Logical scalar. Report progress while the simulations run. |
seed |
Integer scalar or |
Value
An object of class comb_boin_oc_multi, which is a list with components
results |
Named list of |
summary_table |
Data frame with one row per scenario: the true MTD combinations (those closest to |
scenario_names |
Character vector of scenario names. |
n_rows |
Number of dose levels of drug A. |
n_cols |
Number of dose levels of drug B. |
call |
The matched call. |
See Also
Examples
scenarios <- list(
"Two MTD combinations" = matrix(c(0.05, 0.10, 0.20,
0.10, 0.20, 0.30,
0.20, 0.30, 0.45), 3, byrow = TRUE),
"All toxic" = matrix(c(0.40, 0.50, 0.60,
0.50, 0.60, 0.70,
0.60, 0.70, 0.80), 3, byrow = TRUE)
)
oc <- sim_comb_boin_multi(
target = 0.30,
scenarios = scenarios,
n_cohort = 12,
cohort_size = 3,
n_trials = 200,
seed = 123
)
oc
# The full results of one scenario
oc$results[["All toxic"]]
Operating Characteristics of a TITE-BOIN Design
Description
Simulate a time-to-event BOIN (TITE-BOIN) trial many times under one dose-toxicity scenario and summarize how often each dose is selected as the MTD, how many patients are treated and how many DLTs are observed at each dose, how long the trials last and how often accrual is suspended.
Usage
sim_tite_boin(
target,
p_true,
n_cohort,
cohort_size,
window,
accrual_rate,
method = c("imputation", "ess"),
accrual = c("exponential", "uniform", "fixed"),
dlt_time = c("weibull", "uniform"),
late_fraction = 0.5,
prior_weights = c(1, 1, 1)/3,
max_pending_ratio = NULL,
min_completed = NULL,
min_follow_up = 0,
n_trials = 10000,
start_dose = 1,
n_earlystop = 18,
p_saf = NULL,
p_tox = NULL,
cutoff_eli = 0.95,
extrasafe = FALSE,
offset = 0.05,
bound_mtd = FALSE,
mtd_max_estimate = NULL,
min_mtd_sample = 1,
overdose_cutoff = NULL,
n_earlystop_rule = c("with_stay", "simple"),
keep_trials = FALSE,
verbose = FALSE,
seed = 123
)
Arguments
target |
Numeric scalar. Target DLT probability, for example 0.30. |
p_true |
Numeric vector. True DLT probability at each dose level, in increasing dose order. The probability of a DLT within the assessment window. |
n_cohort |
Integer scalar. Number of cohorts in a trial. |
cohort_size |
Integer scalar or vector. Number of patients per cohort. A scalar is used for
every cohort. A vector shorter than |
window |
Numeric scalar. Length of the DLT assessment window. |
accrual_rate |
Numeric scalar. Average number of patients arriving per unit of time, in the
same unit as |
method |
Character scalar, |
accrual |
Character scalar. Distribution of the times between arrivals:
|
dlt_time |
Character scalar. Distribution of the time to DLT within the window:
|
late_fraction |
Numeric scalar strictly between 0 and 1. Share of the DLTs that occur in the second half of the assessment window under the Weibull distribution. Defaults to 0.5, the setting of Yuan et al. (2018) and Lin and Yuan (2020). |
prior_weights |
Numeric vector of three non-negative values. Prior probabilities that a DLT
occurs in the first, second and last third of the assessment window, used
to weight the follow-up of the pending patients in STFT (Yuan et al., 2018,
Supplementary Appendix D) and ESS (Lin and Yuan, 2020, Supplementary S1).
They are rescaled to sum to one. Defaults to equal weights, which give the
unweighted STFT. The decision table does not change with the weights; only
the value compared with its boundaries does. This describes the design and
is separate from |
max_pending_ratio |
Numeric scalar or |
min_completed |
Integer scalar or |
min_follow_up |
Numeric scalar between 0 and 1. Shortest follow-up, as a fraction of
|
n_trials |
Integer scalar. Number of trials to simulate. Defaults to 10000. |
start_dose |
Integer scalar. Dose level for the first cohort. Defaults to 1. |
n_earlystop |
Integer scalar. The trial stops once this many patients have been treated at the current dose and the design would stay there. Defaults to 18. |
p_saf |
Numeric scalar. Highest DLT probability deemed subtherapeutic.
Defaults to |
p_tox |
Numeric scalar. Lowest DLT probability deemed overly toxic.
Defaults to |
cutoff_eli |
Numeric scalar. Posterior probability cutoff for dose elimination. Defaults to 0.95. |
extrasafe |
Logical scalar. Apply the stricter safety stopping rule at the lowest dose.
Defaults to |
offset |
Numeric scalar between 0 and 0.5. Amount by which |
bound_mtd |
Logical scalar. Require the isotonic estimate at the selected dose to be at
or below the de-escalation boundary. Defaults to |
mtd_max_estimate |
Numeric scalar or |
min_mtd_sample |
Integer scalar. Smallest number of patients a dose must have received to be eligible as the MTD. Defaults to 1. |
overdose_cutoff |
Numeric scalar or |
n_earlystop_rule |
Character scalar, either |
keep_trials |
Logical scalar. Keep the full trial by trial data in the result.
Defaults to |
verbose |
Logical scalar. Report progress while the simulation runs.
Defaults to |
seed |
Integer scalar or |
Details
The trials are simulated by tite_boin_simulate, whose details
describe the conduct of a trial. Once every patient has completed the
assessment the MTD is selected from the final data exactly as in
sim_boin, with boin_select_mtd, and a trial
stopped for safety selects no dose.
When no patient is ever pending at a decision, for example with
accrual = "fixed" and window shorter than
1 / accrual_rate, every result agrees with that of
sim_boin under the same seed.
Value
An object of class c("tite_boin_oc", "boin_oc"), which has every
component of the result of sim_boin, so that code written
for sim_boin() also reads it, and in addition
duration_mean |
Average trial duration, from the first arrival until
every enrolled patient has completed the assessment, in the time unit of
|
duration_sd |
Standard deviation of the trial duration. |
pct_trials_suspended |
Percentage of trials in which accrual was suspended at least once. |
avg_n_suspensions |
Average number of suspensions per trial. |
avg_time_suspended |
Average total time with accrual suspended per trial. |
The trials component, when kept, also holds duration,
n_suspensions and time_suspended for every trial.
References
Yuan, Y., Lin, R., Li, D., Nie, L. and Warren, K. E. (2018). Time-to-Event Bayesian Optimal Interval Design to Accelerate Phase I Trials. Clinical Cancer Research, 24(20), 4921-4930.
Lin, R. and Yuan, Y. (2020). Time-to-Event Model-Assisted Designs for Dose-Finding Trials with Delayed Toxicity. Biostatistics, 21(4), 807-824.
See Also
tite_boin_simulate, sim_tite_boin_multi,
sim_boin
Examples
# A three month window with two patients a month
oc <- sim_tite_boin(
target = 0.30,
p_true = c(0.05, 0.15, 0.30, 0.45, 0.60),
n_cohort = 10,
cohort_size = 3,
window = 3,
accrual_rate = 2,
n_trials = 500,
seed = 123
)
oc
# The effective sample size of Lin and Yuan (2020)
oc_ess <- sim_tite_boin(
target = 0.30,
p_true = c(0.05, 0.15, 0.30, 0.45, 0.60),
n_cohort = 12,
cohort_size = 3,
window = 3,
accrual_rate = 2,
method = "ess",
n_trials = 10000,
seed = 123
)
oc_ess
Operating Characteristics of a TITE-BOIN Design Across Several Scenarios
Description
Run sim_tite_boin under a list of dose-toxicity scenarios that
share the same design, and collect the results into one table.
Usage
sim_tite_boin_multi(
target,
scenarios,
n_cohort,
cohort_size,
window,
accrual_rate,
method = c("imputation", "ess"),
accrual = c("exponential", "uniform", "fixed"),
dlt_time = c("weibull", "uniform"),
late_fraction = 0.5,
prior_weights = c(1, 1, 1)/3,
max_pending_ratio = NULL,
min_completed = NULL,
min_follow_up = 0,
n_trials = 10000,
start_dose = 1,
n_earlystop = 18,
p_saf = NULL,
p_tox = NULL,
cutoff_eli = 0.95,
extrasafe = FALSE,
offset = 0.05,
bound_mtd = FALSE,
mtd_max_estimate = NULL,
min_mtd_sample = 1,
overdose_cutoff = NULL,
n_earlystop_rule = c("with_stay", "simple"),
keep_trials = FALSE,
verbose = FALSE,
seed = 123
)
Arguments
target |
Numeric scalar. Target DLT probability, for example 0.30. |
scenarios |
A list of scenarios. Each element is a list with a |
n_cohort |
Integer scalar. Number of cohorts in a trial. |
cohort_size |
Integer scalar or vector. Number of patients per cohort. A scalar is used for
every cohort. A vector shorter than |
window |
Numeric scalar. Length of the DLT assessment window. |
accrual_rate |
Numeric scalar. Average number of patients arriving per unit of time, in the
same unit as |
method |
Character scalar, |
accrual |
Character scalar. Distribution of the times between arrivals:
|
dlt_time |
Character scalar. Distribution of the time to DLT within the window:
|
late_fraction |
Numeric scalar strictly between 0 and 1. Share of the DLTs that occur in the second half of the assessment window under the Weibull distribution. Defaults to 0.5, the setting of Yuan et al. (2018) and Lin and Yuan (2020). |
prior_weights |
Numeric vector of three non-negative values. Prior probabilities that a DLT
occurs in the first, second and last third of the assessment window, used
to weight the follow-up of the pending patients in STFT (Yuan et al., 2018,
Supplementary Appendix D) and ESS (Lin and Yuan, 2020, Supplementary S1).
They are rescaled to sum to one. Defaults to equal weights, which give the
unweighted STFT. The decision table does not change with the weights; only
the value compared with its boundaries does. This describes the design and
is separate from |
max_pending_ratio |
Numeric scalar or |
min_completed |
Integer scalar or |
min_follow_up |
Numeric scalar between 0 and 1. Shortest follow-up, as a fraction of
|
n_trials |
Integer scalar. Number of trials to simulate. Defaults to 10000. |
start_dose |
Integer scalar. Dose level for the first cohort. Defaults to 1. |
n_earlystop |
Integer scalar. The trial stops once this many patients have been treated at the current dose and the design would stay there. Defaults to 18. |
p_saf |
Numeric scalar. Highest DLT probability deemed subtherapeutic.
Defaults to |
p_tox |
Numeric scalar. Lowest DLT probability deemed overly toxic.
Defaults to |
cutoff_eli |
Numeric scalar. Posterior probability cutoff for dose elimination. Defaults to 0.95. |
extrasafe |
Logical scalar. Apply the stricter safety stopping rule at the lowest dose.
Defaults to |
offset |
Numeric scalar between 0 and 0.5. Amount by which |
bound_mtd |
Logical scalar. Require the isotonic estimate at the selected dose to be at
or below the de-escalation boundary. Defaults to |
mtd_max_estimate |
Numeric scalar or |
min_mtd_sample |
Integer scalar. Smallest number of patients a dose must have received to be eligible as the MTD. Defaults to 1. |
overdose_cutoff |
Numeric scalar or |
n_earlystop_rule |
Character scalar, either |
keep_trials |
Logical scalar. Keep the trial by trial data of every scenario.
Defaults to |
verbose |
Logical scalar. Report progress while the simulations run.
Defaults to |
seed |
Integer scalar or |
Value
An object of class c("tite_boin_oc_multi", "boin_oc_multi"), which
is a list with components
results |
Named list of |
summary_table |
Data frame collecting all scenarios, with the four rows
of |
scenario_names |
Character vector of scenario names. |
n_doses |
Number of dose levels. |
call |
The matched call. |
See Also
Examples
scenarios <- list(
list(name = "MTD at dose 3", p_true = c(0.05, 0.15, 0.30, 0.45, 0.60)),
list(name = "All toxic", p_true = c(0.35, 0.45, 0.55, 0.65, 0.75))
)
oc <- sim_tite_boin_multi(
target = 0.30,
scenarios = scenarios,
n_cohort = 10,
cohort_size = 3,
window = 3,
accrual_rate = 2,
n_trials = 200,
seed = 123
)
oc
Decision Table for the TITE-BOIN Design
Description
Tabulate the dose assignment rule of the time-to-event Bayesian optimal interval (TITE-BOIN) design, which allows new patients to be treated while the DLT assessment of earlier patients is still pending. For every attainable combination of patients treated, DLTs observed and patients pending at the current dose, the table gives the decision or, when the decision depends on how long the pending patients have been followed, the values of the follow-up statistic at which it changes.
Usage
tite_boin_decision_table(
target,
max_n,
method = c("imputation", "ess"),
p_saf = NULL,
p_tox = NULL,
cutoff_eli = 0.95,
max_pending_ratio = NULL,
min_completed = NULL,
min_follow_up = 0
)
Arguments
target |
Numeric scalar. Target DLT probability, for example 0.30. |
max_n |
Integer scalar. Largest number of patients treated at a single dose. |
method |
Character scalar. How the pending patients enter the estimate of the DLT
probability: |
p_saf |
Numeric scalar. Highest DLT probability deemed subtherapeutic.
Defaults to |
p_tox |
Numeric scalar. Lowest DLT probability deemed overly toxic.
Defaults to |
cutoff_eli |
Numeric scalar. Posterior probability cutoff for dose elimination. Defaults to 0.95. |
max_pending_ratio |
Numeric scalar greater than 0 and at most 1. Accrual is suspended when the
proportion of the patients at the current dose whose assessment is pending
exceeds this value, unless the dose is de-escalated whatever their outcomes.
Defaults to 0.5 for |
min_completed |
Integer scalar. While some patients are pending, escalation requires at
least this many patients at the current dose to have completed the
assessment, and accrual is suspended instead when fewer have. Defaults to 0
for |
min_follow_up |
Numeric scalar between 0 and 1. While some patients are pending, escalation also requires the shortest follow-up among the pending patients at the current dose, as a fraction of the assessment window (MF), to be at least this value, and accrual is suspended instead when it is not. Defaults to 0, which never suspends on this ground. Chen et al. (2025) recommend 0.25, their rule 2 with B = 25. The rule leaves the boundaries on the follow-up statistic unchanged, so it is recorded as an attribute rather than in the rows of the table. |
Details
Suppose that n patients have been treated at the current dose, that r of them
have completed the DLT assessment with n_tox DLTs, and that
c = n - r are pending. The standardized total follow-up time (STFT) is the
sum of the follow-up times of the pending patients divided by the length of
the assessment window, so that STFT lies between 0 and c. With no pending
patient the decision is that of the BOIN design, taken from
boin_boundary.
method = "imputation" replaces each pending outcome by its expected
value under a uniform time to DLT. The estimate of the DLT probability is
(n_tox + q * (c - STFT)) / n, where q = p / (1 - p) and
p = (n_tox + a) / (r + 1) is the posterior mean under a
Beta(a, 1 - a) prior with a = target / 2 (Yuan et al., 2018,
Supplementary Appendix A). The estimate decreases as STFT grows, so the rule
becomes a pair of boundaries on STFT. As in the BOIN design, escalation is
possible only while n_tox / n is below the target and de-escalation
only once it reaches the target.
method = "ess" uses the approximated likelihood of Lin and Yuan
(2020), under which the estimate is n_tox / ESS with the effective
sample size ESS = r + STFT, which lies between r and n. The dose is escalated
when ESS is at least n_tox / lambda_e and de-escalated when it is at
most n_tox / lambda_d. The boundaries in the table refer to ESS.
The rules are applied in this order: elimination; de-escalation that holds
whatever the outcomes of the pending patients, that is when
n_tox / n is at least lambda_d; suspension for too many
pending patients; and finally the boundaries on the follow-up statistic, in
which an escalation blocked by min_completed becomes a suspension.
An escalation that remains is then subject to min_follow_up.
Elimination requires Pr(p > target | data) > cutoff_eli computed
with all n treated patients, the pending ones counted as without DLT, which
is how both articles define it. It is not evaluated before three patients
have been treated.
Neither the length of the assessment window nor the weights given to the follow-up times change the table, because both enter only through STFT. A weighted STFT, such as that of a piecewise uniform time to DLT, is compared with the same boundaries.
Value
An object of class tite_boin_decision_table, which is a data frame
with one row per attainable state of the current dose, ordered by
n, n_tox and n_pending, and with the columns
n |
Number of patients treated at the current dose, from 1 to
|
n_tox |
Number of DLTs observed, which can only come from patients who completed the assessment. |
n_pending |
Number of patients whose assessment is pending. |
decision |
Decision code. |
esc_bound |
Escalate, or suspend when escalation is blocked, when the
follow-up statistic is at least this value. |
deesc_bound |
De-escalate when the follow-up statistic is at most this
value. |
The design parameters are stored as attributes: method,
statistic ("STFT" or "ESS"), target,
p_saf, p_tox, lambda_e, lambda_d,
cutoff_eli, max_pending_ratio, min_completed and
min_follow_up. When min_follow_up is positive, an
escalation (code "E", or "E" as the first part of a code
with a slash) in a state with pending patients takes place only when MF is
at least min_follow_up, and accrual is suspended otherwise. The
object has print and plot methods.
Agreement with the published tables
With the defaults, method = "imputation" reproduces every entry of
Table 1 (target 0.2) of Yuan et al. (2018) and of Table S1 (target 0.3) of
its supplementary appendix. These tables allow de-escalation when
n_tox / n equals the target (Table 1, 15 patients with 3 DLTs), which
equation (5) of the appendix, read literally, would not. The implementation
follows the tables, which agree with the verbal description of the rule in
the appendix.
With max_pending_ratio = 0.49 and min_follow_up = 0.25,
method = "imputation" reproduces every entry of Table 1 (target 0.3,
up to six patients) of Chen et al. (2025) and of Table A1 (target 0.25, up
to nine patients) of the supplementary materials of Chen et al. (2026).
Their rule 1 suspends accrual when fewer than 51 percent of the patients
have completed the assessment, which for whole numbers of patients is the
same as more than 49 percent pending, unless the observed DLT rate already
exceeds lambda_d; this exception is the de-escalation that holds
whatever the outcomes of the pending patients.
For method = "ess" no table for the BOIN design has been published;
the tables of Lin and Yuan (2020) are for the keyboard and mTPI designs.
References
Yuan, Y., Lin, R., Li, D., Nie, L. and Warren, K. E. (2018). Time-to-Event Bayesian Optimal Interval Design to Accelerate Phase I Trials. Clinical Cancer Research, 24(20), 4921-4930.
Lin, R. and Yuan, Y. (2020). Time-to-Event Model-Assisted Designs for Dose-Finding Trials with Delayed Toxicity. Biostatistics, 21(4), 807-824.
Chen, K., Chen, T.-Y., Zhang, Y., Lin, R. and Yuan, Y. (2025). Practical Considerations for Using the TITE-BOIN Design to Handle Late-Onset Toxicity or Fast Accrual in Phase I Trials. Clinical Cancer Research, 31(13), 2573-2580.
Chen, K., Zhao, Y., Takeda, K. and Yuan, Y. (2026). BE-BOIN: A Dose Optimization Design Accommodating Backfill and Late-Onset Toxicity. Therapeutic Innovation and Regulatory Science. doi:10.1007/s43441-026-00994-0
See Also
print.tite_boin_decision_table,
plot.tite_boin_decision_table,
boin_decision_table
Examples
# Table 1 of Yuan et al. (2018)
decisions <- tite_boin_decision_table(target = 0.2, max_n = 15)
print(decisions, cohort_size = 3)
# Nine patients, one DLT and four pending: escalate once STFT reaches 2.15
decisions[decisions$n == 9 & decisions$n_tox == 1 & decisions$n_pending == 4, ]
# Table 1 of Chen et al. (2025): at least 51 percent of the patients with a
# completed assessment, and escalation only once every pending patient has
# been followed for a quarter of the window
decisions_chen <- tite_boin_decision_table(target = 0.3, max_n = 6,
max_pending_ratio = 0.49,
min_follow_up = 0.25)
print(decisions_chen, cohort_size = 3)
# The effective sample size of Lin and Yuan (2020)
decisions_ess <- tite_boin_decision_table(target = 0.3, max_n = 12, method = "ess")
print(decisions_ess, cohort_size = 3)
Simulate TITE-BOIN Trials
Description
Run the time-to-event BOIN (TITE-BOIN) design over many simulated trials, in which patients arrive over time and new patients are treated while the DLT assessment of earlier patients is still pending. Return the patient and DLT counts at every dose together with the duration of each trial and the time spent with accrual suspended.
Usage
tite_boin_simulate(
target,
p_true,
n_cohort,
cohort_size,
window,
accrual_rate,
method = c("imputation", "ess"),
accrual = c("exponential", "uniform", "fixed"),
dlt_time = c("weibull", "uniform"),
late_fraction = 0.5,
prior_weights = c(1, 1, 1)/3,
max_pending_ratio = NULL,
min_completed = NULL,
min_follow_up = 0,
n_trials = 10000,
start_dose = 1,
n_earlystop = 18,
p_saf = NULL,
p_tox = NULL,
cutoff_eli = 0.95,
extrasafe = FALSE,
offset = 0.05,
n_earlystop_rule = c("with_stay", "simple"),
seed = 123
)
Arguments
target |
Numeric scalar. Target DLT probability, for example 0.30. |
p_true |
Numeric vector. True DLT probability at each dose level, in increasing dose order. The probability of a DLT within the assessment window. |
n_cohort |
Integer scalar. Number of cohorts in a trial. |
cohort_size |
Integer scalar or vector. Number of patients per cohort. A scalar is used for
every cohort. A vector shorter than |
window |
Numeric scalar. Length of the DLT assessment window. |
accrual_rate |
Numeric scalar. Average number of patients arriving per unit of time, in the
same unit as |
method |
Character scalar, |
accrual |
Character scalar. Distribution of the times between arrivals:
|
dlt_time |
Character scalar. Distribution of the time to DLT within the window:
|
late_fraction |
Numeric scalar strictly between 0 and 1. Share of the DLTs that occur in the second half of the assessment window under the Weibull distribution. Defaults to 0.5, the setting of Yuan et al. (2018) and Lin and Yuan (2020). |
prior_weights |
Numeric vector of three non-negative values. Prior probabilities that a DLT
occurs in the first, second and last third of the assessment window, used
to weight the follow-up of the pending patients in STFT (Yuan et al., 2018,
Supplementary Appendix D) and ESS (Lin and Yuan, 2020, Supplementary S1).
They are rescaled to sum to one. Defaults to equal weights, which give the
unweighted STFT. The decision table does not change with the weights; only
the value compared with its boundaries does. This describes the design and
is separate from |
max_pending_ratio |
Numeric scalar or |
min_completed |
Integer scalar or |
min_follow_up |
Numeric scalar between 0 and 1. Shortest follow-up, as a fraction of
|
n_trials |
Integer scalar. Number of trials to simulate. Defaults to 10000. |
start_dose |
Integer scalar. Dose level for the first cohort. Defaults to 1. |
n_earlystop |
Integer scalar. The trial stops once this many patients have been treated at the current dose and the design would stay there. Defaults to 18. |
p_saf |
Numeric scalar. Highest DLT probability deemed subtherapeutic.
Defaults to |
p_tox |
Numeric scalar. Lowest DLT probability deemed overly toxic.
Defaults to |
cutoff_eli |
Numeric scalar. Posterior probability cutoff for dose elimination. Defaults to 0.95. |
extrasafe |
Logical scalar. Apply the stricter safety stopping rule at the lowest dose.
Defaults to |
offset |
Numeric scalar between 0 and 0.5. Amount by which |
n_earlystop_rule |
Character scalar, either |
seed |
Integer scalar or |
Details
Patients arrive one at a time. The dose for a cohort is decided when its
first patient arrives, from the data available at that moment, and the other
patients of the cohort receive the same dose. The decision follows
tite_boin_decision_table. A patient with a DLT completes the
assessment when the DLT occurs, and a patient without one at the end of the
window. When the decision is to suspend accrual, the arriving patient waits
until the next pending patient at the current dose completes the assessment,
or, with a positive min_follow_up, until the last pending patient to
arrive at the current dose has been followed for that fraction of the
window, whichever comes first, and the decision is taken again at that
moment. Later patients arrive after the one who waited.
At every decision the rules are applied in the order used by
boin_simulate: elimination at the current dose and the extra
safety rule, early stopping on n_earlystop, then the dose
transition. Because DLTs can be observed after a dose has been left, the
elimination rule is also checked at the other doses; a dose that meets it is
eliminated together with all higher doses, and the trial moves below it.
Elimination counts every treated patient, the pending ones as without DLT.
One uniform variate is drawn from R's random number stream per patient, in
enrollment order and in the cohort blocks of boin_simulate.
It decides whether the patient has a DLT and, under the Weibull
distribution, gives the time to DLT through the inverse distribution
function, which falls inside the window exactly when there is a DLT. The
times between arrivals come from a second generator (xoshiro256**) seeded
with seed, or with one draw from R's stream when seed is
NULL. As a result, whenever no patient is pending at any decision,
for example with accrual = "fixed" and window shorter than
1 / accrual_rate, the trials are identical to those of
boin_simulate with the same seed.
The follow-up of a pending patient counts towards STFT as the share of the
window already covered, or, with prior_weights, as the prior
probability that a DLT would have occurred by then. Both articles evaluate
their designs with equal weights, the default.
The titration phase and the stay_on_1_of_3 option of
boin_simulate are not available, as neither article defines
them for the time-to-event design.
Value
An object of class tite_boin_trials, which is a list with components
n_pts |
Integer matrix, |
n_tox |
Integer matrix of the same shape, of DLTs, counted once every patient has completed the assessment. |
eliminated |
Logical matrix of the same shape, marking doses eliminated during the trial. |
cohorts_used |
Integer vector of cohorts treated in each trial. |
stop_reason |
Character vector giving why each trial ended, with the
values of |
duration |
Numeric vector. Time from the first arrival until every enrolled patient has completed the assessment. |
n_suspensions |
Integer vector. Number of decisions at which accrual had to be suspended. |
time_suspended |
Numeric vector. Total time with accrual suspended. |
boundary |
The |
settings |
List of the design parameters. |
References
Yuan, Y., Lin, R., Li, D., Nie, L. and Warren, K. E. (2018). Time-to-Event Bayesian Optimal Interval Design to Accelerate Phase I Trials. Clinical Cancer Research, 24(20), 4921-4930.
Lin, R. and Yuan, Y. (2020). Time-to-Event Model-Assisted Designs for Dose-Finding Trials with Delayed Toxicity. Biostatistics, 21(4), 807-824.
See Also
tite_boin_decision_table, boin_simulate
Examples
# A three month window with two patients a month
trials <- tite_boin_simulate(
target = 0.30,
p_true = c(0.05, 0.15, 0.30, 0.45, 0.60),
n_cohort = 10,
cohort_size = 3,
window = 3,
accrual_rate = 2,
n_trials = 200,
seed = 123
)
trials
summary(trials$duration)