Title: | Posterior Predictive (PoP) Design for Phase I Clinical Trials |
---|---|
Description: | The primary goal of phase I clinical trials is to find the maximum tolerated dose (MTD). To reach this objective, we introduce a new design for phase I clinical trials, the posterior predictive (PoP) design. The PoP design is an innovative model-assisted design that is as simply as the conventional algorithmic designs as its decision rules can be pre-tabulated prior to the onset of trial, but is of more flexibility of selecting diverse target toxicity rates and cohort sizes. The PoP design has desirable properties, such as coherence and consistency. Moreover, the PoP design provides better empirical performance than the BOIN and Keyboard design with respect to high average probabilities of choosing the MTD and slightly lower risk of treating patients at subtherapeutic or overly toxic doses. |
Authors: | Chenqi Fu [aut], Xinying Fang [aut, cre], Shouhao Zhou [aut] |
Maintainer: | Xinying Fang <[email protected]> |
License: | GPL-2 |
Version: | 1.1.0 |
Built: | 2024-10-29 06:34:54 UTC |
Source: | CRAN |
Use this function to generate the dose escalation and deescalation boundaries for single-agent trials.
get.boundary.pop(target, n, cohortsize, cutoff, K, cutoff_e)
get.boundary.pop(target, n, cohortsize, cutoff, K, cutoff_e)
target |
the target DLT rate |
n |
total sample size |
cohortsize |
the cohort size |
cutoff |
the cutoff for the predictive Bayes Factor (PrBF). Users can specify either a value or a function
for cutoff. If PrBF < cutoff, we assign the next cohort of patients to an adjacent dose based on observed DLT.
Otherwise, the evidence is in favor of |
K |
number of dose levels. It is required when argument cutoff is a function that requires K. |
cutoff_e |
the cutoff for the dose exclusion rule. If |
We assume that there are pre-specified dose levels of the drug of interest. Let
denote
these dose levels. The dose-limiting toxicity (DLT) is assessed as a binary outcome, experiencing
toxicity or not. The true dose toxicity is monotonically increasing as the dose level increases.
Let
be the target toxicity rate and
be the true dose-toxicity of dose level
, for
.
We formulate our hypothesis as:
indicates that
is the desired MTD so that we should stay;
reflects the current dose is
either below or above the MTD so that we should transit to a lower or upper dose level. Whether
escalate or de-escalate the dose is straightforward: if the observed toxicity rate is above the target
toxicity rate
, we de-escalate the dose; if the observed toxicity rate is below
, we escalate the dose.
With the hypothesis, the predictive Bayes factor comparing and
is given by
where is the toxicity response of the ith subject among
subjects that received dose
, for
.
denotes the sum of toxicity response. We assume that
According to the calibration of the PrBF, a decision rule based on is:
1. If
, the evidence is in favor of
and we need to retain the current dose;
2. Otherwise, we assign the next cohort of patients to an adjacent dose according to the observed
DLT
, such as:
(a) If , we escalate the dose;
(b) If , we de-escalate the dose.
For patient safety and trial efficiency, the PoP design employs a dose exclusion rule. On the one hand, if the PrBF based on the observed DLT indicates a dose is above the MTD with a certain evidence, we exclude the current dose and doses above to avoid treating patients at an overly toxic dose; on the other hand, if the PrBF implies that a dose is substantially below the MTD, we eliminate the current dose and doses below to prevent wasting patients at a subtherapeutic dose. Such a dose exclusion rule is as follow:
If , the evidence is in favor of
and:
1. If , the current dose is deemed as subtherapeutic and we exclude the current dose and lower doses;
2. If , the current dose is overly toxic and we exclude the current dose and higher doses.
Once all the doses are eliminated from further investigation, the trial is terminated early.
The selection of the cut-off value for the dose exclusion is critical for the performance of the PoP
design, because it ensure the safety of the patients and efficiency of the design by influencing
the early termination rule. The exclusion boundaries in the table above were determined using
.
get.boundary.pop()
returns a list object, including the corresponding decision tables
$out.boundary
and $out.full.boundary
.
## get the dose escalation and deescalation boundaries for PoP design with ## the target DLT rate of 0.3, maximum sample size of 30, and cohort size of 3 bound <- get.boundary.pop(target=0.5, n = 15, cohortsize = 3, cutoff=2.5,K=4,cutoff_e=5/24) summary(bound) # get the descriptive summary of the boundary plot(bound) # plot the flowchart of the design along with decision boundaries
## get the dose escalation and deescalation boundaries for PoP design with ## the target DLT rate of 0.3, maximum sample size of 30, and cohort size of 3 bound <- get.boundary.pop(target=0.5, n = 15, cohortsize = 3, cutoff=2.5,K=4,cutoff_e=5/24) summary(bound) # get the descriptive summary of the boundary plot(bound) # plot the flowchart of the design along with decision boundaries
Generate the operating characteristics of the PoP design by simulating trials.
get.oc.pop(target,n,cohortsize,titration,skeleton,n.trial,cutoff,cutoff_e, risk.cutoff,earlyterm,start,seed)
get.oc.pop(target,n,cohortsize,titration,skeleton,n.trial,cutoff,cutoff_e, risk.cutoff,earlyterm,start,seed)
target |
the target DLT rate |
n |
total sample size |
cohortsize |
the cohort size |
titration |
default is TRUE. Set |
skeleton |
a vector containing the true toxicity probabilities of the investigational dose levels. |
n.trial |
the total number of trials to be simulated |
cutoff |
the cutoff for the predictive Bayes Factor (PrBF). Users can specify either a value or a function
for cutoff. If PrBF < cutoff, we assign the next cohort of patients to an adjacent dose based on observed DLT.
Otherwise, the evidence is in favor of |
cutoff_e |
the cutoff for the dose exclusion rule. If |
risk.cutoff |
the cutoff to eliminate an over/under toxic dose.
We recommend the default value of ( |
earlyterm |
the early termination parameter. |
start |
specify the starting dose level. Default value is 1. |
seed |
the seed for random number generation. Default is 123. |
TBD
get.oc.pop()
returns the operating characteristics of the PoP design as a list,
including:
(1) selection percentage at each dose level ($sel.pct
),
(2) the number of patients treated at each dose level ($num.p
),
(3) the number of toxicities observed at each dose level ($num.tox
),
(4) the average number of toxicities,
(5) the average number of patients,
(6) the percentage of early stopping without selecting the MTD ($early
),
(7) risk of underdosing 80% or more of patients ($risk.under
),
(8) risk of overdosing 80% or more of patients ($risk.over
)
Brunk, H., Barlow, R. E., Bartholomew, D. J. & Bremner, J. M (1972, ISBN-13: 978-0471049708).
## get the operating characteristics for single-agent trials oc <- get.oc.pop(target=0.3,n=15,cohortsize=3,titration=TRUE, cutoff=2.5,cutoff_e=5/24, skeleton=c(0.3,0.4,0.5,0.6),n.trial=1000, risk.cutoff=0.8,earlyterm=TRUE,start=1, seed=123) summary(oc) # summarize design operating characteristics plot(oc)
## get the operating characteristics for single-agent trials oc <- get.oc.pop(target=0.3,n=15,cohortsize=3,titration=TRUE, cutoff=2.5,cutoff_e=5/24, skeleton=c(0.3,0.4,0.5,0.6),n.trial=1000, risk.cutoff=0.8,earlyterm=TRUE,start=1, seed=123) summary(oc) # summarize design operating characteristics plot(oc)
Plot the objects returned by other functions, including (1) flowchart of PoP design; (2) operating characteristics of the design, including selection percentage and the number of patients treated at each dose; (3) the estimate of toxicity probability for each dose and corresponding 95% credible interval
## S3 method for class 'pop' plot(x, ...)
## S3 method for class 'pop' plot(x, ...)
x |
the object returned by other functions |
... |
ignored arguments |
plot()
returns a figure or a series of figures depending on the object entered
Generate descriptive summary for objects returned by other functions.
## S3 method for class 'pop' print(x, ...)
## S3 method for class 'pop' print(x, ...)
x |
the object returned by other functions |
... |
ignored arguments |
print()
prints the objects returned by other functions.
print()
prints the objects returned by other functions.
Select the maximum tolerated dose (MTD) when the single-agent trial is completed
select.mtd.pop(target, n.pts, n.tox)
select.mtd.pop(target, n.pts, n.tox)
target |
the target DLT rate |
n.pts |
a vector containing the number of patients treated at each dose level |
n.tox |
a vector containing the number of patients who experienced dose-limiting toxicity at each dose level |
select.mtd.pop()
returns (1) selected MTD ($MTD
),
(2) isotonic estimate of the DLT probablity at each dose and associated
Brunk, H., Barlow, R. E., Bartholomew, D. J. & Bremner, J. M (1972, ISBN-13: 978-0471049708).
### select the MTD for PoP trial n <- c(4, 4, 16, 8, 0) y <- c(0, 0, 5, 5, 0) selmtd <- select.mtd.pop(target=0.3,n.pts=n, n.tox=y) summary(selmtd) plot(selmtd)
### select the MTD for PoP trial n <- c(4, 4, 16, 8, 0) y <- c(0, 0, 5, 5, 0) selmtd <- select.mtd.pop(target=0.3,n.pts=n, n.tox=y) summary(selmtd) plot(selmtd)
Generate descriptive summary for objects returned by other functions.
## S3 method for class 'pop' summary(object, ...)
## S3 method for class 'pop' summary(object, ...)
object |
the object returned by other functions. |
... |
ignored arguments |
summary()
prints the objects returned by other functions.
## summarize the results returned by get.boundary.pop() bound <- get.boundary.pop(n = 15, cohortsize = 3, target=0.3, cutoff=exp(1), K=3,cutoff_e=exp(-1)) summary(bound) ## summarize the results returned by get.oc.pop() oc <- get.oc.pop(target=0.3,n=15,cohortsize=3,titration=TRUE, cutoff=TRUE,cutoff_e=exp(-1),skeleton=c(0.3,0.4,0.5,0.6),n.trial=1000, risk.cutoff=0.8,earlyterm=TRUE,start=1) summary(oc) ### summarize the results returned by select.mtd.pop() n <- c(3, 3, 15, 9, 0) y <- c(0, 0, 4, 4, 0) selmtd <- select.mtd.pop(target=0.3,n.pts=n, n.tox=y) summary(selmtd)
## summarize the results returned by get.boundary.pop() bound <- get.boundary.pop(n = 15, cohortsize = 3, target=0.3, cutoff=exp(1), K=3,cutoff_e=exp(-1)) summary(bound) ## summarize the results returned by get.oc.pop() oc <- get.oc.pop(target=0.3,n=15,cohortsize=3,titration=TRUE, cutoff=TRUE,cutoff_e=exp(-1),skeleton=c(0.3,0.4,0.5,0.6),n.trial=1000, risk.cutoff=0.8,earlyterm=TRUE,start=1) summary(oc) ### summarize the results returned by select.mtd.pop() n <- c(3, 3, 15, 9, 0) y <- c(0, 0, 4, 4, 0) selmtd <- select.mtd.pop(target=0.3,n.pts=n, n.tox=y) summary(selmtd)