| Type: | Package |
| Title: | Fast Simulation of Bayesian Optimal Interval Designs for Phase I Trials |
| Version: | 2.0.0 |
| Date: | 2026-09-18 |
| 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. |
| License: | MIT + file LICENSE |
| Encoding: | UTF-8 |
| Depends: | R (≥ 3.5.0) |
| Imports: | Rcpp (≥ 1.0.0), stats, utils |
| LinkingTo: | Rcpp |
| Suggests: | BOIN, ggplot2 (≥ 3.4.0), Iso, knitr, rmarkdown, spelling, testthat (≥ 3.0.0) |
| Language: | en-US |
| URL: | 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-09-18 11:34:37 UTC; i_lik |
| Author: | Gosuke Homma |
| Maintainer: | Gosuke Homma <my.name.is.gosuke@gmail.com> |
| Repository: | CRAN |
| Date/Publication: | 2026-09-18 15:00:13 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.
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.
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.
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.
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), ]
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)
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"))
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 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)
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 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