Title: | Adaptive Optimal Two-Stage Designs |
---|---|
Description: | Optimize one or two-arm, two-stage designs for clinical trials with respect to several implemented objective criteria or custom objectives. Optimization under uncertainty and conditional (given stage-one outcome) constraints are supported. See Pilz et al. (2019) <doi:10.1002/sim.8291> and Kunzmann et al. (2021) <doi:10.18637/jss.v098.i09> for details. |
Authors: | Kevin Kunzmann [aut, cph] , Maximilian Pilz [aut, cre] , Jan Meis [aut] , Nico Bruder [aut] |
Maintainer: | Maximilian Pilz <[email protected]> |
License: | MIT + file LICENSE |
Version: | 1.1.1.9000 |
Built: | 2024-11-02 05:29:42 UTC |
Source: | https://github.com/optad/adoptr |
The adoptr package provides functionality to explore custom optimal two-stage designs for one- or two-arm superiority tests. For more details on the theoretical background see doi:10.1002/sim.8291 and doi:10.18637/jss.v098.i09. adoptr makes heavy use of the S4 class system. A good place to start learning about it can be found here.
For a sample workflow and a quick demo of the capabilities, see here.
A more detailed description of the background and the usage of adoptr can be found here or here doi:10.18637/jss.v098.i09 .
A variety of examples is presented in the validation report hosted here.
adoptr currently supports TwoStageDesign
,
GroupSequentialDesign
, and OneStageDesign
.
The implemented data distributions are Normal
, Binomial
,
Student
, Survival
, ChiSquared
(including
Pearson2xK
and ZSquared
) and ANOVA
.
Both ContinuousPrior
and PointMassPrior
are
supported for the single parameter of a DataDistribution
.
See Scores
for information on the basic system of representing
scores.
Available scores are ConditionalPower
,
ConditionalSampleSize
, Power
, and
ExpectedSampleSize
.
Maintainer: Maximilian Pilz [email protected] (ORCID)
Authors:
Kevin Kunzmann [email protected] (ORCID) [copyright holder]
Jan Meis [email protected] (ORCID)
Nico Bruder [email protected] (ORCID)
Useful links:
Report bugs at https://github.com/optad/adoptr/issues
ANOVA is used to test whether there is a significant difference between the means of groups.
The sample size which adoptr
returns is the group wise sample size.
The function get_tau_ANOVA
is used to obtain a parameter ,
which is used in the same way as
to describe the difference of
means between the groups.
ANOVA(n_groups) get_tau_ANOVA(means, common_sd = 1)
ANOVA(n_groups) get_tau_ANOVA(means, common_sd = 1)
n_groups |
number of groups to be compared |
means |
vector denoting the mean per group |
common_sd |
standard deviation of the groups |
see probability_density_function
and
cumulative_distribution_function
to evaluate the pdf
and the cdf, respectively. Use NestedModels
to get insights
in the implementation of ANOVA
.
model <- ANOVA(3L) H1 <- PointMassPrior(get_tau_ANOVA(c(0.4, 0.8, 0.5)), 1)
model <- ANOVA(3L) H1 <- PointMassPrior(get_tau_ANOVA(c(0.4, 0.8, 0.5)), 1)
Implements the L1-norm of the design's stage-two sample size function. The average of the stage-two sample size without weighting with the data distribution is computed. This can be interpreted as integration over a unifrom prior on the continuation region.
AverageN2(label = NA_character_) ## S4 method for signature 'AverageN2,TwoStageDesign' evaluate(s, design, optimization = FALSE, subdivisions = 10000L, ...)
AverageN2(label = NA_character_) ## S4 method for signature 'AverageN2,TwoStageDesign' evaluate(s, design, optimization = FALSE, subdivisions = 10000L, ...)
label |
object label (string) |
s |
|
design |
object |
optimization |
logical, if |
subdivisions |
number of subdivisions to use for adaptive integration (only affects non-optimization code) |
... |
further optional arguments |
an object of class AverageN2
N1
for penalizing n1 values
avn2 <- AverageN2() evaluate( AverageN2(), TwoStageDesign(100, 0.5, 1.5, 60.0, 1.96, order = 5L) ) # 60
avn2 <- AverageN2() evaluate( AverageN2(), TwoStageDesign(100, 0.5, 1.5, 60.0, 1.96, order = 5L) ) # 60
Implements the normal approximation for a test on rates.
The reponse rate in the control group,
rC, has to be specified by
rate_control
.
The null hypothesis is:
rE ≤ rC,
where rE denotes the response rate
in the invervention group.
It is tested against the alternative
rE > rC.
The test statistic is given as
X1 = √n (rE - rC) / √(2 r0 (1-r0)),
where r0 denotes the mean between
rE and
rC in the two-armed case,
and rE in the one-armed case.#'
All priors have to be defined for the rate difference
rE - rC.
Binomial(rate_control, two_armed = TRUE) ## S4 method for signature 'Binomial' quantile(x, probs, n, theta, ...) ## S4 method for signature 'Binomial,numeric' simulate(object, nsim, n, theta, seed = NULL, ...)
Binomial(rate_control, two_armed = TRUE) ## S4 method for signature 'Binomial' quantile(x, probs, n, theta, ...) ## S4 method for signature 'Binomial,numeric' simulate(object, nsim, n, theta, seed = NULL, ...)
rate_control |
assumed response rate in control group |
two_armed |
logical indicating if a two-armed trial is regarded |
x |
outcome |
probs |
vector of probabilities |
n |
sample size |
theta |
distribution parameter |
... |
further optional arguments |
object |
object of class |
nsim |
number of simulation runs |
seed |
random seed |
Note that simulate
for class Binomial
simulates the
normal approximation of the test statistic.
rate_control
cf. parameter 'rate_control'
see probability_density_function
and
cumulative_distribution_function
to evaluate the pdf
and the cdf, respectively.
datadist <- Binomial(rate_control = 0.2, two_armed = FALSE)
datadist <- Binomial(rate_control = 0.2, two_armed = FALSE)
bounds()
returns the range of the support of a prior or data distribution.
bounds(dist, ...) ## S4 method for signature 'ContinuousPrior' bounds(dist, ...) ## S4 method for signature 'PointMassPrior' bounds(dist, ...)
bounds(dist, ...) ## S4 method for signature 'ContinuousPrior' bounds(dist, ...) ## S4 method for signature 'PointMassPrior' bounds(dist, ...)
dist |
a univariate |
... |
further optional arguments |
numeric
of length two, c(lower, upper)
bounds(ContinuousPrior(function(x) dunif(x, .2, .4), c(.2, .4))) # > 0.2 0.4 bounds(PointMassPrior(c(0, .5), c(.3, .7))) # > 0.3 0.7
bounds(ContinuousPrior(function(x) dunif(x, .2, .4), c(.2, .4))) # > 0.2 0.4 bounds(PointMassPrior(c(0, .5), c(.3, .7))) # > 0.3 0.7
Methods to access the stage-two critical values of a
TwoStageDesign
.
c2
returns the stage-two critical value conditional on the stage-one test
statistic.
c2(d, x1, ...) ## S4 method for signature 'TwoStageDesign,numeric' c2(d, x1, ...) ## S4 method for signature 'OneStageDesign,numeric' c2(d, x1, ...)
c2(d, x1, ...) ## S4 method for signature 'TwoStageDesign,numeric' c2(d, x1, ...) ## S4 method for signature 'OneStageDesign,numeric' c2(d, x1, ...)
d |
design |
x1 |
stage-one test statistic |
... |
further optional arguments |
the critical value function c2
of design d
at position x1
TwoStageDesign
, see n
for accessing
the sample size of a design
design <- TwoStageDesign( n1 = 25, c1f = 0, c1e = 2.5, n2 = 50, c2 = 1.96, order = 7L ) c2(design, 2.2) # 1.96 c2(design, 3.0) # -Inf c2(design, -1.0) # Inf design <- TwoStageDesign( n1 = 25, c1f = 0, c1e = 2.5, n2 = 50, c2 = 1.96, order = 7L ) c2(design, 2.2) # 1.96 c2(design, 3.0) # -Inf c2(design, -1.0) # Inf
design <- TwoStageDesign( n1 = 25, c1f = 0, c1e = 2.5, n2 = 50, c2 = 1.96, order = 7L ) c2(design, 2.2) # 1.96 c2(design, 3.0) # -Inf c2(design, -1.0) # Inf design <- TwoStageDesign( n1 = 25, c1f = 0, c1e = 2.5, n2 = 50, c2 = 1.96, order = 7L ) c2(design, 2.2) # 1.96 c2(design, 3.0) # -Inf c2(design, -1.0) # Inf
Implements a chi-squared distribution. The classes Pearson2xk
and ZSquared
are subclasses, used in two different situations.
Pearson2xK
is used when testing k groups for homogeneity in
response rates. The null hypothesis is
r1=...=rk, and the
alternative is that there exists a pair of groups with differing rates.
ZSquared
implements the square of a normally distributed random variable
with mean and standard deviation
.
ChiSquared(df) ## S4 method for signature 'ChiSquared' quantile(x, probs, n, theta, ...) ## S4 method for signature 'ChiSquared,numeric' simulate(object, nsim, n, theta, seed = NULL, ...)
ChiSquared(df) ## S4 method for signature 'ChiSquared' quantile(x, probs, n, theta, ...) ## S4 method for signature 'ChiSquared,numeric' simulate(object, nsim, n, theta, seed = NULL, ...)
df |
number of degrees of freedom |
x |
outcome |
probs |
vector of probabilities |
n |
sample size |
theta |
distribution parameter |
... |
further optional arguments |
object |
object of class |
nsim |
number of simulation runs |
seed |
random seed |
see probability_density_function
and
cumulative_distribution_function
to evaluate the pdf
and the cdf, respectively.
datadist <- ChiSquared(df=4)
datadist <- ChiSquared(df=4)
composite
defines new composite scores by point-wise evaluation of
scores in any valid numerical expression.
composite(expr, label = NA_character_) ## S4 method for signature 'CompositeScore,TwoStageDesign' evaluate(s, design, ...)
composite(expr, label = NA_character_) ## S4 method for signature 'CompositeScore,TwoStageDesign' evaluate(s, design, ...)
expr |
Expression (in curly brackets); must contain at least one score variable; if multiple scores are used, they must either all be conditional or unconditional. Currently, no non-score variables are supported |
label |
object label (string) |
s |
object of class |
design |
object |
... |
further optional arguments |
an object of class CompositeConditionalScore
or
CompositeUnconditionalScore
depending on the class of the scores used
in expr
ess <- ExpectedSampleSize(Normal(), PointMassPrior(.4, 1)) power <- Power(Normal(), PointMassPrior(.4, 1)) # linear combination: composite({ess - 50*power}) # control flow (e.g. for and while loops) composite({ res <- 0 for (i in 1:3) { res <- res + ess } res }) # functional composition composite({log(ess)}) cp <- ConditionalPower(Normal(), PointMassPrior(.4, 1)) composite({3*cp})
ess <- ExpectedSampleSize(Normal(), PointMassPrior(.4, 1)) power <- Power(Normal(), PointMassPrior(.4, 1)) # linear combination: composite({ess - 50*power}) # control flow (e.g. for and while loops) composite({ res <- 0 for (i in 1:3) { res <- res + ess } res }) # functional composition composite({log(ess)}) cp <- ConditionalPower(Normal(), PointMassPrior(.4, 1)) composite({3*cp})
Restrict an object of class Prior
to a sub-interval and
re-normalize the PDF.
condition(dist, interval, ...) ## S4 method for signature 'ContinuousPrior,numeric' condition(dist, interval, ...) ## S4 method for signature 'PointMassPrior,numeric' condition(dist, interval, ...)
condition(dist, interval, ...) ## S4 method for signature 'ContinuousPrior,numeric' condition(dist, interval, ...) ## S4 method for signature 'PointMassPrior,numeric' condition(dist, interval, ...)
dist |
a univariate |
interval |
length-two numeric vector giving the parameter interval to condition on |
... |
further optional arguments |
conditional Prior
on given interval
tmp <- condition( ContinuousPrior(function(x) dunif(x, .2, .4), c(.2, .4)), c(.3, .5) ) bounds(tmp) # c(.3, .4) tmp <- condition(PointMassPrior(c(0, .5), c(.3, .7)), c(-1, .25)) expectation(tmp, identity) # 0
tmp <- condition( ContinuousPrior(function(x) dunif(x, .2, .4), c(.2, .4)), c(.3, .5) ) bounds(tmp) # c(.3, .4) tmp <- condition(PointMassPrior(c(0, .5), c(.3, .7)), c(-1, .25)) expectation(tmp, identity) # 0
This score evaluates P[X2 > c2(design, X1) | X1 = x1]. Note that the distribution of X2 is the posterior predictive after observing X1 = x1.
ConditionalPower(dist, prior, label = "Pr[x2>=c2(x1)|x1]") Power(dist, prior, label = "Pr[x2>=c2(x1)]") ## S4 method for signature 'ConditionalPower,TwoStageDesign' evaluate(s, design, x1, optimization = FALSE, ...)
ConditionalPower(dist, prior, label = "Pr[x2>=c2(x1)|x1]") Power(dist, prior, label = "Pr[x2>=c2(x1)]") ## S4 method for signature 'ConditionalPower,TwoStageDesign' evaluate(s, design, x1, optimization = FALSE, ...)
dist |
a univariate |
prior |
a |
label |
object label (string) |
s |
|
design |
object |
x1 |
stage-one test statistic |
optimization |
logical, if |
... |
further optional arguments |
prior <- PointMassPrior(.4, 1) cp <- ConditionalPower(Normal(), prior) evaluate( cp, TwoStageDesign(50, .0, 2.0, 50, 2.0, order = 5L), x1 = 1 ) # these two are equivalent: expected(cp, Normal(), prior) Power(Normal(), prior)
prior <- PointMassPrior(.4, 1) cp <- ConditionalPower(Normal(), prior) evaluate( cp, TwoStageDesign(50, .0, 2.0, 50, 2.0, order = 5L), x1 = 1 ) # these two are equivalent: expected(cp, Normal(), prior) Power(Normal(), prior)
This score simply evaluates n(d, x1)
for a design d
and the
first-stage outcome x1
.
The data distribution and prior are only relevant when it is integrated.
ConditionalSampleSize(label = "n(x1)") ExpectedSampleSize(dist, prior, label = "E[n(x1)]") ExpectedNumberOfEvents(dist, prior, label = "E[n(x1)]") ## S4 method for signature 'ConditionalSampleSize,TwoStageDesign' evaluate(s, design, x1, optimization = FALSE, ...)
ConditionalSampleSize(label = "n(x1)") ExpectedSampleSize(dist, prior, label = "E[n(x1)]") ExpectedNumberOfEvents(dist, prior, label = "E[n(x1)]") ## S4 method for signature 'ConditionalSampleSize,TwoStageDesign' evaluate(s, design, x1, optimization = FALSE, ...)
label |
object label (string) |
dist |
a univariate |
prior |
a |
s |
|
design |
object |
x1 |
stage-one test statistic |
optimization |
logical, if |
... |
further optional arguments |
design <- TwoStageDesign(50, .0, 2.0, 50, 2.0, order = 5L) prior <- PointMassPrior(.4, 1) css <- ConditionalSampleSize() evaluate(css, design, c(0, .5, 3)) ess <- ExpectedSampleSize(Normal(), prior) ene <- ExpectedNumberOfEvents(Survival(0.7), PointMassPrior(1.7, 1)) # those two are equivalent evaluate(ess, design) evaluate(expected(css, Normal(), prior), design)
design <- TwoStageDesign(50, .0, 2.0, 50, 2.0, order = 5L) prior <- PointMassPrior(.4, 1) css <- ConditionalSampleSize() evaluate(css, design, c(0, .5, 3)) ess <- ExpectedSampleSize(Normal(), prior) ene <- ExpectedNumberOfEvents(Survival(0.7), PointMassPrior(1.7, 1)) # those two are equivalent evaluate(ess, design) evaluate(expected(css, Normal(), prior), design)
Conceptually, constraints work very similar to scores (any score can be put in a constraint). Currently, constraints of the form 'score <=/>= x', 'x <=/>= score' and 'score <=/>= score' are admissible.
## S4 method for signature 'Constraint,TwoStageDesign' evaluate(s, design, optimization = FALSE, ...) ## S4 method for signature 'ConditionalScore,numeric' e1 <= e2 ## S4 method for signature 'ConditionalScore,numeric' e1 >= e2 ## S4 method for signature 'numeric,ConditionalScore' e1 <= e2 ## S4 method for signature 'numeric,ConditionalScore' e1 >= e2 ## S4 method for signature 'ConditionalScore,ConditionalScore' e1 <= e2 ## S4 method for signature 'ConditionalScore,ConditionalScore' e1 >= e2 ## S4 method for signature 'UnconditionalScore,numeric' e1 <= e2 ## S4 method for signature 'UnconditionalScore,numeric' e1 >= e2 ## S4 method for signature 'numeric,UnconditionalScore' e1 <= e2 ## S4 method for signature 'numeric,UnconditionalScore' e1 >= e2 ## S4 method for signature 'UnconditionalScore,UnconditionalScore' e1 <= e2 ## S4 method for signature 'UnconditionalScore,UnconditionalScore' e1 >= e2
## S4 method for signature 'Constraint,TwoStageDesign' evaluate(s, design, optimization = FALSE, ...) ## S4 method for signature 'ConditionalScore,numeric' e1 <= e2 ## S4 method for signature 'ConditionalScore,numeric' e1 >= e2 ## S4 method for signature 'numeric,ConditionalScore' e1 <= e2 ## S4 method for signature 'numeric,ConditionalScore' e1 >= e2 ## S4 method for signature 'ConditionalScore,ConditionalScore' e1 <= e2 ## S4 method for signature 'ConditionalScore,ConditionalScore' e1 >= e2 ## S4 method for signature 'UnconditionalScore,numeric' e1 <= e2 ## S4 method for signature 'UnconditionalScore,numeric' e1 >= e2 ## S4 method for signature 'numeric,UnconditionalScore' e1 <= e2 ## S4 method for signature 'numeric,UnconditionalScore' e1 >= e2 ## S4 method for signature 'UnconditionalScore,UnconditionalScore' e1 <= e2 ## S4 method for signature 'UnconditionalScore,UnconditionalScore' e1 >= e2
s |
|
design |
object |
optimization |
logical, if |
... |
further optional arguments |
e1 |
left hand side (score or numeric) |
e2 |
right hand side (score or numeric) |
an object of class Constraint
design <- OneStageDesign(50, 1.96) cp <- ConditionalPower(Normal(), PointMassPrior(0.4, 1)) pow <- Power(Normal(), PointMassPrior(0.4, 1)) # unconditional power constraint constraint1 <- pow >= 0.8 evaluate(constraint1, design) # conditional power constraint constraint2 <- cp >= 0.7 evaluate(constraint2, design, .5) constraint3 <- 0.7 <= cp # same as constraint2 evaluate(constraint3, design, .5)
design <- OneStageDesign(50, 1.96) cp <- ConditionalPower(Normal(), PointMassPrior(0.4, 1)) pow <- Power(Normal(), PointMassPrior(0.4, 1)) # unconditional power constraint constraint1 <- pow >= 0.8 evaluate(constraint1, design) # conditional power constraint constraint2 <- cp >= 0.7 evaluate(constraint2, design, .5) constraint3 <- 0.7 <= cp # same as constraint2 evaluate(constraint3, design, .5)
ContinuousPrior
is a sub-class of Prior
implementing
a generic representation of continuous prior distributions over a compact
interval on the real line.
ContinuousPrior( pdf, support, order = 10, label = NA_character_, tighten_support = FALSE, check_normalization = TRUE )
ContinuousPrior( pdf, support, order = 10, label = NA_character_, tighten_support = FALSE, check_normalization = TRUE )
pdf |
vectorized univariate PDF function |
support |
numeric vector of length two with the bounds of the compact interval on which the pdf is positive. |
order |
|
label |
object label (string) |
tighten_support |
logical indicating if the support should be tightened |
check_normalization |
logical indicating if it should be checked
that |
pdf
cf. parameter 'pdf'
support
cf. parameter 'support'
pivots
normalized pivots for integration rule (in [-1, 1]) the actual pivots are scaled to the support of the prior
weights
weights of of integration rule at pivots
for
approximating integrals over delta
Discrete priors are supported via PointMassPrior
ContinuousPrior(function(x) 2*x, c(0, 1))
ContinuousPrior(function(x) 2*x, c(0, 1))
cumulative_distribution_function
evaluates the cumulative distribution
function of a specific distribution dist
at a point x
.
cumulative_distribution_function(dist, x, n, theta, ...) ## S4 method for signature 'Binomial,numeric,numeric,numeric' cumulative_distribution_function(dist, x, n, theta, ...) ## S4 method for signature 'ChiSquared,numeric,numeric,numeric' cumulative_distribution_function(dist, x, n, theta, ...) ## S4 method for signature 'NestedModels,numeric,numeric,numeric' cumulative_distribution_function(dist, x, n, theta, ...) ## S4 method for signature 'Normal,numeric,numeric,numeric' cumulative_distribution_function(dist, x, n, theta, ...) ## S4 method for signature 'Student,numeric,numeric,numeric' cumulative_distribution_function(dist, x, n, theta, ...) ## S4 method for signature 'Survival,numeric,numeric,numeric' cumulative_distribution_function(dist, x, n, theta, ...)
cumulative_distribution_function(dist, x, n, theta, ...) ## S4 method for signature 'Binomial,numeric,numeric,numeric' cumulative_distribution_function(dist, x, n, theta, ...) ## S4 method for signature 'ChiSquared,numeric,numeric,numeric' cumulative_distribution_function(dist, x, n, theta, ...) ## S4 method for signature 'NestedModels,numeric,numeric,numeric' cumulative_distribution_function(dist, x, n, theta, ...) ## S4 method for signature 'Normal,numeric,numeric,numeric' cumulative_distribution_function(dist, x, n, theta, ...) ## S4 method for signature 'Student,numeric,numeric,numeric' cumulative_distribution_function(dist, x, n, theta, ...) ## S4 method for signature 'Survival,numeric,numeric,numeric' cumulative_distribution_function(dist, x, n, theta, ...)
dist |
a univariate |
x |
outcome |
n |
sample size |
theta |
distribution parameter |
... |
further optional arguments |
If the distribution is Binomial
,
theta denotes the rate difference between
intervention and control group.
Then, the mean is assumed to be
√ n theta.
If the distribution is Normal
, then
the mean is assumed to be
√ n theta.
value of the cumulative distribution function at point x
.
cumulative_distribution_function(Binomial(.1, TRUE), 1, 50, .3) cumulative_distribution_function(Pearson2xK(3), 1, 30, get_tau_Pearson2xK(c(0.3,0.4,0.7,0.2))) cumulative_distribution_function(ZSquared(TRUE), 1, 35, get_tau_ZSquared(0.4, 1)) cumulative_distribution_function(ANOVA(3), 1, 30, get_tau_ANOVA(c(0.3, 0.4, 0.7, 0.2))) cumulative_distribution_function(Normal(), 1, 50, .3) cumulative_distribution_function(Student(two_armed = FALSE), .75, 50, .9) cumulative_distribution_function(Survival(0.6,TRUE),0.75,50,0.9)
cumulative_distribution_function(Binomial(.1, TRUE), 1, 50, .3) cumulative_distribution_function(Pearson2xK(3), 1, 30, get_tau_Pearson2xK(c(0.3,0.4,0.7,0.2))) cumulative_distribution_function(ZSquared(TRUE), 1, 35, get_tau_ZSquared(0.4, 1)) cumulative_distribution_function(ANOVA(3), 1, 30, get_tau_ANOVA(c(0.3, 0.4, 0.7, 0.2))) cumulative_distribution_function(Normal(), 1, 50, .3) cumulative_distribution_function(Student(two_armed = FALSE), .75, 50, .9) cumulative_distribution_function(Survival(0.6,TRUE),0.75,50,0.9)
DataDistribution
is an abstract class used to represent the distribution
of a sufficient statistic x
given a sample size n
and a
single parameter value theta
.
x |
outcome |
n |
sample size |
theta |
distribution parameter |
... |
further optional arguments |
This abstraction layer allows the representation of t-distributions
(unknown variance), normal distribution (known variance), and normal
approximation of a binary endpoint.
Currently, the two implemented versions are Normal-class
and
Binomial-class
.
The logical option two_armed
allows to decide whether a one-arm or
a two-arm (the default) design should be computed. In the case of a two-arm
design all sample sizes are per group.
two_armed
Logical that indicates if a two-arm design is assumed.
normaldist <- Normal(two_armed = FALSE) binomialdist <- Binomial(rate_control = .25, two_armed = TRUE)
normaldist <- Normal(two_armed = FALSE) binomialdist <- Binomial(rate_control = .25, two_armed = TRUE)
Computes the expected value of a vectorized, univariate function f
with respect to a distribution dist
.
I.e., E[f(X)].
expectation(dist, f, ...) ## S4 method for signature 'ContinuousPrior,function' expectation(dist, f, ...) ## S4 method for signature 'PointMassPrior,function' expectation(dist, f, ...)
expectation(dist, f, ...) ## S4 method for signature 'ContinuousPrior,function' expectation(dist, f, ...) ## S4 method for signature 'PointMassPrior,function' expectation(dist, f, ...)
dist |
a univariate |
f |
a univariate function, must be vectorized |
... |
further optional arguments |
numeric
, expected value of f
with respect to dist
expectation( ContinuousPrior(function(x) dunif(x, .2, .4), c(.2, .4)), identity ) # > 0.3 expectation(PointMassPrior(c(0, .5), c(.3, .7)), identity) # > .35
expectation( ContinuousPrior(function(x) dunif(x, .2, .4), c(.2, .4)), identity ) # > 0.3 expectation(PointMassPrior(c(0, .5), c(.3, .7)), identity) # > .35
The optimization method minimize
requires an initial
design for optimization.
This function provides a variety of possibilities to hand-craft designs that
fulfill type I error and type II error constraints which may be used as initial designs.
get_initial_design( theta, alpha, beta, type_design = c("two-stage", "group-sequential", "one-stage"), type_c2 = c("linear_decreasing", "constant"), type_n2 = c("optimal", "constant", "linear_decreasing", "linear_increasing"), dist = Normal(), cf, ce, info_ratio = 0.5, slope, weight = sqrt(info_ratio), order = 7L, ... )
get_initial_design( theta, alpha, beta, type_design = c("two-stage", "group-sequential", "one-stage"), type_c2 = c("linear_decreasing", "constant"), type_n2 = c("optimal", "constant", "linear_decreasing", "linear_increasing"), dist = Normal(), cf, ce, info_ratio = 0.5, slope, weight = sqrt(info_ratio), order = 7L, ... )
theta |
the alternative effect size in the normal case, the rate difference under the alternative in the binomial case |
alpha |
maximal type I error rate |
beta |
maximal type II error rate |
type_design |
type of design |
type_c2 |
either linear-decreasing c2-function according to inverse normal combination test or constant c2 |
type_n2 |
design of n2-function |
dist |
distribution of the test statistic |
cf |
first-stage futility boundary |
ce |
first-stage efficacy boundary. Note that specifying this boundary implies that the type I error constraint might not be fulfilled anymore |
info_ratio |
the ratio between first and second stage sample size |
slope |
slope of n2 function |
weight |
weight of first stage test statistics in inverse normal combination test |
order |
desired integration order |
... |
further optional arguments |
The distribution of the test statistic is specified by dist
.
The default assumes a two-armed z-test.
The first stage efficacy boundary and the boundary are chosen as Pocock-boundaries, so either
if
is constant or
, where the null hypothesis is rejected if
.
By specifying
, it's clear that the boundaries are not Pocock-boundaries anymore, so the type I error
constraint may not be fulfilled.
IMPORTANT: When using the t-distribution or ANOVA, the design does probably
not keep the type I and type II error, only approximate designs are returned.
An object of class TwoStageDesign
.
init <- get_initial_design( theta = 0.3, alpha = 0.025, beta = 0.2, type_design="two-stage", type_c2="linear_decreasing", type_n2="linear_increasing", dist=Normal(), cf=0.7, info_ratio=0.5, slope=23, weight = 1/sqrt(3) )
init <- get_initial_design( theta = 0.3, alpha = 0.025, beta = 0.2, type_design="two-stage", type_c2="linear_decreasing", type_n2="linear_increasing", dist=Normal(), cf=0.7, info_ratio=0.5, slope=23, weight = 1/sqrt(3) )
The optimization method minimize
is based on the package
nloptr
. This requires upper and lower boundaries for optimization.
Such boundaries can be computed via lower_boundary_design
respectively upper_boundary_design
.
They are implemented by default in minimize
.
Note that minimize
allows the user to define its own
boundary designs, too.
get_lower_boundary_design(initial_design, ...) get_upper_boundary_design(initial_design, ...) ## S4 method for signature 'OneStageDesign' get_lower_boundary_design(initial_design, n1 = 1, c1_buffer = 2, ...) ## S4 method for signature 'GroupSequentialDesign' get_lower_boundary_design( initial_design, n1 = 1, n2_pivots = 1, c1_buffer = 2, c2_buffer = 2, ... ) ## S4 method for signature 'TwoStageDesign' get_lower_boundary_design( initial_design, n1 = 1, n2_pivots = 1, c1_buffer = 2, c2_buffer = 2, ... ) ## S4 method for signature 'OneStageDesign' get_upper_boundary_design( initial_design, n1 = 5 * initial_design@n1, c1_buffer = 2, ... ) ## S4 method for signature 'GroupSequentialDesign' get_upper_boundary_design( initial_design, n1 = 5 * initial_design@n1, n2_pivots = 5 * initial_design@n2_pivots, c1_buffer = 2, c2_buffer = 2, ... ) ## S4 method for signature 'TwoStageDesign' get_upper_boundary_design( initial_design, n1 = 5 * initial_design@n1, n2_pivots = 5 * initial_design@n2_pivots, c1_buffer = 2, c2_buffer = 2, ... )
get_lower_boundary_design(initial_design, ...) get_upper_boundary_design(initial_design, ...) ## S4 method for signature 'OneStageDesign' get_lower_boundary_design(initial_design, n1 = 1, c1_buffer = 2, ...) ## S4 method for signature 'GroupSequentialDesign' get_lower_boundary_design( initial_design, n1 = 1, n2_pivots = 1, c1_buffer = 2, c2_buffer = 2, ... ) ## S4 method for signature 'TwoStageDesign' get_lower_boundary_design( initial_design, n1 = 1, n2_pivots = 1, c1_buffer = 2, c2_buffer = 2, ... ) ## S4 method for signature 'OneStageDesign' get_upper_boundary_design( initial_design, n1 = 5 * initial_design@n1, c1_buffer = 2, ... ) ## S4 method for signature 'GroupSequentialDesign' get_upper_boundary_design( initial_design, n1 = 5 * initial_design@n1, n2_pivots = 5 * initial_design@n2_pivots, c1_buffer = 2, c2_buffer = 2, ... ) ## S4 method for signature 'TwoStageDesign' get_upper_boundary_design( initial_design, n1 = 5 * initial_design@n1, n2_pivots = 5 * initial_design@n2_pivots, c1_buffer = 2, c2_buffer = 2, ... )
initial_design |
The initial design |
... |
optional arguments The values |
n1 |
bound for the first-stage sample size n1 |
c1_buffer |
shift of the early-stopping boundaries from the initial ones |
n2_pivots |
bound for the second-stage sample size n2 |
c2_buffer |
shift of the final decision boundary from the initial one |
An object of class TwoStageDesign
.
initial_design <- TwoStageDesign( n1 = 25, c1f = 0, c1e = 2.5, n2 = 50, c2 = 1.96, order = 7L ) get_lower_boundary_design(initial_design)
initial_design <- TwoStageDesign( n1 = 25, c1f = 0, c1e = 2.5, n2 = 50, c2 = 1.96, order = 7L ) get_lower_boundary_design(initial_design)
Group-sequential designs are a sub-class of the TwoStageDesign
class with constant stage-two sample size.
See TwoStageDesign
for slot details.
Any group-sequential design can be converted to a fully flexible
TwoStageDesign
(see examples section).
GroupSequentialDesign(n1, ...) ## S4 method for signature 'numeric' GroupSequentialDesign( n1, c1f, c1e, n2_pivots, c2_pivots, order = NULL, event_rate, ... ) ## S4 method for signature 'GroupSequentialDesign' TwoStageDesign(n1, event_rate, ...) ## S4 method for signature 'GroupSequentialDesignSurvival' TwoStageDesign(n1, ...)
GroupSequentialDesign(n1, ...) ## S4 method for signature 'numeric' GroupSequentialDesign( n1, c1f, c1e, n2_pivots, c2_pivots, order = NULL, event_rate, ... ) ## S4 method for signature 'GroupSequentialDesign' TwoStageDesign(n1, event_rate, ...) ## S4 method for signature 'GroupSequentialDesignSurvival' TwoStageDesign(n1, ...)
n1 |
stage one sample size or |
... |
further optional arguments |
c1f |
early futility stopping boundary |
c1e |
early efficacy stopping boundary |
n2_pivots |
numeric of length one, stage-two sample size |
c2_pivots |
numeric vector, stage-two critical values on the integration pivot points |
order |
of the Gaussian quadrature rule to use for integration, set to length(c2_pivots) if NULL, otherwise first value of c2_pivots is repeated 'order'-times. |
event_rate |
probability that a subject in either group will eventually have an event, only needs to be specified for time-to-event endpoints. |
TwoStageDesign
for superclass and inherited methods
design <- GroupSequentialDesign(25, 0, 2, 25, c(1, 1.5, 2.5)) summary(design) design_survival <- GroupSequentialDesign(25, 0, 2, 25, c(1, 1.5, 2.5), event_rate = 0.7) TwoStageDesign(design) TwoStageDesign(design_survival)
design <- GroupSequentialDesign(25, 0, 2, 25, c(1, 1.5, 2.5)) summary(design) design_survival <- GroupSequentialDesign(25, 0, 2, 25, c(1, 1.5, 2.5), event_rate = 0.7) TwoStageDesign(design) TwoStageDesign(design_survival)
Group-sequential designs for time-to-event-endpoints are a subclass of both
TwoStageDesignSurvival
and GroupSequentialDesign
.
TwoStageDesignSurvival-class
and GroupSequentialDesign-class
for superclasses and inherited methods.
The methods make_fixed
and make_tunable
can be used to modify
the 'tunability' status of parameters in a TwoStageDesign
object.
Tunable parameters are optimized over, non-tunable ('fixed') parameters are
considered given and not altered during optimization.
make_tunable(x, ...) ## S4 method for signature 'TwoStageDesign' make_tunable(x, ...) make_fixed(x, ...) ## S4 method for signature 'TwoStageDesign' make_fixed(x, ...)
make_tunable(x, ...) ## S4 method for signature 'TwoStageDesign' make_tunable(x, ...) make_fixed(x, ...) ## S4 method for signature 'TwoStageDesign' make_fixed(x, ...)
x |
|
... |
unquoted names of slots for which the tunability status should be changed. |
an updated object of class TwoStageDesign
TwoStageDesign
, tunable_parameters
for
converting tunable parameters of a design object to a numeric vector (and back),
and minimize
for the actual minimzation procedure
design <- TwoStageDesign(25, 0, 2, 25, 2, order = 5) # default: all parameters are tunable (except integration pivots, # weights and tunability status itself) design@tunable # make n1 and the pivots of n2 fixed (not changed during optimization) design <- make_fixed(design, n1, n2_pivots) design@tunable # make them tunable again design <- make_tunable(design, n1, n2_pivots) design@tunable
design <- TwoStageDesign(25, 0, 2, 25, 2, order = 5) # default: all parameters are tunable (except integration pivots, # weights and tunability status itself) design@tunable # make n1 and the pivots of n2 fixed (not changed during optimization) design <- make_fixed(design, n1, n2_pivots) design@tunable # make them tunable again design <- make_tunable(design, n1, n2_pivots) design@tunable
This score evaluates max(n(d))
for a design d
.
MaximumSampleSize(label = "max(n(x1))") ## S4 method for signature 'MaximumSampleSize,TwoStageDesign' evaluate(s, design, optimization = FALSE, ...)
MaximumSampleSize(label = "max(n(x1))") ## S4 method for signature 'MaximumSampleSize,TwoStageDesign' evaluate(s, design, optimization = FALSE, ...)
label |
object label (string) |
s |
|
design |
object |
optimization |
logical, if |
... |
further optional arguments |
Scores for general scores and ConditionalSampleSize for evaluating the sample size point-wise.
design <- TwoStageDesign(50, .0, 2.0, 50, 2.0, order = 5L) mss <- MaximumSampleSize() evaluate(mss, design)
design <- TwoStageDesign(50, .0, 2.0, 50, 2.0, order = 5L) mss <- MaximumSampleSize() evaluate(mss, design)
minimize
takes an unconditional score and
a constraint set (or no constraint) and solves the corresponding
minimization problem using
nloptr
(using COBYLA by default).
An initial design has to be defined. It is also possible to define
lower- and upper-boundary designs. If this is not done, the boundaries are
determined automatically heuristically.
minimize( objective, subject_to, initial_design, lower_boundary_design = get_lower_boundary_design(initial_design), upper_boundary_design = get_upper_boundary_design(initial_design), c2_decreasing = FALSE, check_constraints = TRUE, opts = list(algorithm = "NLOPT_LN_COBYLA", xtol_rel = 1e-05, maxeval = 10000), ... )
minimize( objective, subject_to, initial_design, lower_boundary_design = get_lower_boundary_design(initial_design), upper_boundary_design = get_upper_boundary_design(initial_design), c2_decreasing = FALSE, check_constraints = TRUE, opts = list(algorithm = "NLOPT_LN_COBYLA", xtol_rel = 1e-05, maxeval = 10000), ... )
objective |
objective function |
subject_to |
constraint collection |
initial_design |
initial guess (x0 for nloptr) |
lower_boundary_design |
design specifying the lower boundary. |
upper_boundary_design |
design specifying the upper boundary |
c2_decreasing |
if TRUE, the c2_pivots are forced to be monotonically decreasing |
check_constraints |
if TRUE, it is checked if constrains are fulfilled |
opts |
options list passed to nloptr |
... |
further optional arguments passed to |
a list with elements:
design |
The resulting optimal design |
nloptr_return |
Output of the corresponding nloptr call |
call_args |
The arguments given to the optimization call |
# Define Type one error rate toer <- Power(Normal(), PointMassPrior(0.0, 1)) # Define Power at delta = 0.4 pow <- Power(Normal(), PointMassPrior(0.4, 1)) # Define expected sample size at delta = 0.4 ess <- ExpectedSampleSize(Normal(), PointMassPrior(0.4, 1)) # Compute design minimizing ess subject to power and toer constraints minimize( ess, subject_to( toer <= 0.025, pow >= 0.9 ), initial_design = TwoStageDesign(50, .0, 2.0, 60.0, 2.0, 5L) )
# Define Type one error rate toer <- Power(Normal(), PointMassPrior(0.0, 1)) # Define Power at delta = 0.4 pow <- Power(Normal(), PointMassPrior(0.4, 1)) # Define expected sample size at delta = 0.4 ess <- ExpectedSampleSize(Normal(), PointMassPrior(0.4, 1)) # Compute design minimizing ess subject to power and toer constraints minimize( ess, subject_to( toer <= 0.025, pow >= 0.9 ), initial_design = TwoStageDesign(50, .0, 2.0, 60.0, 2.0, 5L) )
Methods to access the stage-one, stage-two, or overall sample size of a
TwoStageDesign
.
n1
returns the first-stage sample size of a design,
n2
the stage-two sample size conditional on the stage-one test
statistic and n
the overall sample size n1 + n2
.
Internally, objects of the class TwoStageDesign
allow non-natural,
real sample sizes to allow smooth optimization (cf. minimize
for
details).
The optional argument round
allows to switch between the internal
real representation and a rounded version (rounding to the next positive
integer).
n1(d, ...) ## S4 method for signature 'TwoStageDesign' n1(d, round = TRUE, ...) n2(d, x1, ...) ## S4 method for signature 'TwoStageDesign,numeric' n2(d, x1, round = TRUE, ...) n(d, x1, ...) ## S4 method for signature 'TwoStageDesign,numeric' n(d, x1, round = TRUE, ...) ## S4 method for signature 'OneStageDesign,numeric' n2(d, x1, ...) ## S4 method for signature 'GroupSequentialDesign,numeric' n2(d, x1, round = TRUE, ...)
n1(d, ...) ## S4 method for signature 'TwoStageDesign' n1(d, round = TRUE, ...) n2(d, x1, ...) ## S4 method for signature 'TwoStageDesign,numeric' n2(d, x1, round = TRUE, ...) n(d, x1, ...) ## S4 method for signature 'TwoStageDesign,numeric' n(d, x1, round = TRUE, ...) ## S4 method for signature 'OneStageDesign,numeric' n2(d, x1, ...) ## S4 method for signature 'GroupSequentialDesign,numeric' n2(d, x1, round = TRUE, ...)
d |
design |
... |
further optional arguments |
round |
|
x1 |
stage-one test statistic |
sample size value of design d
at point x1
TwoStageDesign
, see c2
for accessing
the critical values
design <- TwoStageDesign( n1 = 25, c1f = 0, c1e = 2.5, n2 = 50, c2 = 1.96, order = 7L ) n1(design) # 25 design@n1 # 25 n(design, x1 = 2.2) # 75
design <- TwoStageDesign( n1 = 25, c1f = 0, c1e = 2.5, n2 = 50, c2 = 1.96, order = 7L ) n1(design) # 25 design@n1 # 25 n(design, x1 = 2.2) # 75
N1
is a class that computes the n1
value of a design.
This can be used as a score in minimize
.
N1(label = NA_character_) ## S4 method for signature 'N1,TwoStageDesign' evaluate(s, design, optimization = FALSE, ...)
N1(label = NA_character_) ## S4 method for signature 'N1,TwoStageDesign' evaluate(s, design, optimization = FALSE, ...)
label |
object label (string) |
s |
|
design |
object |
optimization |
logical, if |
... |
further optional arguments |
an object of class N1
See AverageN2
for a regularization of
the second-stage sample size.
n1_score <- N1() evaluate( N1(), TwoStageDesign(70, 0, 2, rep(60, 6), rep(1.7, 6)) ) # 70
n1_score <- N1() evaluate( N1(), TwoStageDesign(70, 0, 2, rep(60, 6), rep(1.7, 6)) ) # 70
Implements the F-distribution used for an ANOVA or for the comparison of the fit of two
nested regression models. In both cases, the test statistic follows a F-distribution.
NestedModel
is used to compare the fit of two regression models, where one model contains
the independent variables of the smaller model as a subset. Then, one can use ANOVA to determine
whether more variance can be explained by adding more independent variables.
In the class ANOVA
, the number of independent variables of the smaller model is set to
in order to match the degrees of freedom and we obtain a one-way ANOVA.
NestedModels(p_inner, p_outer) ## S4 method for signature 'NestedModels' quantile(x, probs, n, theta, ...) ## S4 method for signature 'NestedModels,numeric' simulate(object, nsim, n, theta, seed = NULL, ...)
NestedModels(p_inner, p_outer) ## S4 method for signature 'NestedModels' quantile(x, probs, n, theta, ...) ## S4 method for signature 'NestedModels,numeric' simulate(object, nsim, n, theta, seed = NULL, ...)
p_inner |
number of independent variables in smaller model |
p_outer |
number of independent variables in bigger model |
x |
outcome |
probs |
vector of probabilities |
n |
sample size |
theta |
distribution parameter |
... |
further optional arguments |
object |
object of class |
nsim |
number of simulation runs |
seed |
random seed |
p_inner
number of parameters in smaller model
p_outer
number of parameters in bigger model
See probability_density_function
and
cumulative_distribution_function
to evaluate the pdf
and the cdf, respectively. Use ANOVA
for detailed information
of ANOVA.
model <- NestedModels(2, 4)
model <- NestedModels(2, 4)
Implements a normal data distribution for z-values given an observed z-value
and stage size.
Standard deviation is 1 and mean θ √n where
θ is the standardized effect size.
The option two_armed
can be set to decide whether a one-arm or a
two-arm design should be computed.
Normal(two_armed = TRUE) ## S4 method for signature 'Normal' quantile(x, probs, n, theta, ...) ## S4 method for signature 'Normal,numeric' simulate(object, nsim, n, theta, seed = NULL, ...)
Normal(two_armed = TRUE) ## S4 method for signature 'Normal' quantile(x, probs, n, theta, ...) ## S4 method for signature 'Normal,numeric' simulate(object, nsim, n, theta, seed = NULL, ...)
two_armed |
logical indicating if a two-armed trial is regarded |
x |
outcome |
probs |
vector of probabilities |
n |
sample size |
theta |
distribution parameter |
... |
further optional arguments |
object |
object of class |
nsim |
number of simulation runs |
seed |
random seed |
See DataDistribution-class
for more details.
see probability_density_function
and
cumulative_distribution_function
to evaluate the pdf
and the cdf, respectively.
datadist <- Normal(two_armed = TRUE)
datadist <- Normal(two_armed = TRUE)
OneStageDesign
implements a one-stage design as special case of
a two-stage design, i.e. as sub-class of TwoStageDesign
.
This is possible by defining n2 = 0,
c = c1f = c1e,
c2(x1) = ifelse(x1< c, Inf, -Inf).
No integration pivots etc are required (set to NaN
).
OneStageDesign(n, ...) ## S4 method for signature 'numeric' OneStageDesign(n, c, event_rate) ## S4 method for signature 'OneStageDesign' TwoStageDesign(n1, event_rate, order = 5L, eps = 0.01, ...) ## S4 method for signature 'OneStageDesignSurvival' TwoStageDesign(n1, order = 5L, eps = 0.01, ...) ## S4 method for signature 'OneStageDesign' plot(x, y, ...)
OneStageDesign(n, ...) ## S4 method for signature 'numeric' OneStageDesign(n, c, event_rate) ## S4 method for signature 'OneStageDesign' TwoStageDesign(n1, event_rate, order = 5L, eps = 0.01, ...) ## S4 method for signature 'OneStageDesignSurvival' TwoStageDesign(n1, order = 5L, eps = 0.01, ...) ## S4 method for signature 'OneStageDesign' plot(x, y, ...)
n |
sample size (stage-one sample size) |
... |
further optional arguments |
c |
rejection boundary (c = c1f = c1e) |
event_rate |
probability that a subject in either group will eventually have an event, only needs to be specified for time-to-event endpoints. |
n1 |
|
order |
integer >= 2, default is 5; order of Gaussian quadrature integration rule to use for new TwoStageDesign. |
eps |
numeric > 0, default = .01; the single critical value c must be split in a continuation interval [c1f, c1e]; this is given by c +/- eps. |
x |
design to plot |
y |
not used |
Note that the default plot,TwoStageDesign-method
method
is not supported for OneStageDesign
objects.
TwoStageDesign
, GroupSequentialDesign-class
design <- OneStageDesign(30, 1.96) summary(design) design_twostage <- TwoStageDesign(design) summary(design_twostage) design_survival <- OneStageDesign(30, 1.96, 0.7) TwoStageDesign(design_survival)
design <- OneStageDesign(30, 1.96) summary(design) design_twostage <- TwoStageDesign(design) summary(design_twostage) design_survival <- OneStageDesign(30, 1.96, 0.7) TwoStageDesign(design_survival)
OneStageDesignSurvival
is a subclass of both OneStageDesign
and
TwoStageDesignSurvival
.
TwoStageDesignSurvival-class
and OneStageDesign-class
for superclasses and inherited methods.
When we test for homogeneity of rates in a k-armed trial with binary endpoints,
the test statistic is chi-squared distributed with degrees of
freedom under the null. Under the alternative, the statistic is chi-squared
distributed with a non-centrality parameter
.
The function
get_tau_Pearson2xk
then computes , such that
is given as
, where
is the number of
subjects per group. In
adoptr
, is used in the same way as
in the case of the normally distributed test statistic.
Pearson2xK(n_groups) get_tau_Pearson2xK(p_vector)
Pearson2xK(n_groups) get_tau_Pearson2xK(p_vector)
n_groups |
number of groups considered for testing procedure |
p_vector |
vector denoting the event rates per group |
pearson <- Pearson2xK(3) H1 <- PointMassPrior(get_tau_Pearson2xK(c(.3, .25, .4)), 1)
pearson <- Pearson2xK(3) H1 <- PointMassPrior(get_tau_Pearson2xK(c(.3, .25, .4)), 1)
TwoStageDesign
with optional set of conditional scoresThis method allows to plot the stage-two sample size and decision boundary functions of a chosen design.
## S4 method for signature 'TwoStageDesign' plot(x, y = NULL, ..., rounded = TRUE, k = 100)
## S4 method for signature 'TwoStageDesign' plot(x, y = NULL, ..., rounded = TRUE, k = 100)
x |
design to plot |
y |
not used |
... |
further named |
rounded |
should n-values be rounded? |
k |
number of points to use for plotting |
TwoStageDesign
and
user-defined elements of the class ConditionalScore
.
a plot of the two-stage design
design <- TwoStageDesign(50, 0, 2, 50, 2, 5) cp <- ConditionalPower(dist = Normal(), prior = PointMassPrior(.4, 1)) plot(design, "Conditional Power" = cp, cex.axis = 2)
design <- TwoStageDesign(50, 0, 2, 50, 2, 5) cp <- ConditionalPower(dist = Normal(), prior = PointMassPrior(.4, 1)) plot(design, "Conditional Power" = cp, cex.axis = 2)
PointMassPrior
is a sub-class of Prior
representing a univariate prior over a discrete set of points with positive
probability mass.
PointMassPrior(theta, mass, label = NA_character_)
PointMassPrior(theta, mass, label = NA_character_)
theta |
numeric vector of pivot points with positive prior mass |
mass |
numeric vector of probability masses at the pivot points (must sum to 1) |
label |
object label (string) |
an object of class PointMassPrior
, theta
is
automatically sorted in ascending order
theta
cf. parameter 'theta'
mass
cf. parameter 'mass'
To represent continuous prior distributions use ContinuousPrior
.
PointMassPrior(c(0, .5), c(.3, .7))
PointMassPrior(c(0, .5), c(.3, .7))
Return posterior distribution given observing stage-one outcome.
posterior(dist, prior, x1, n1, ...) ## S4 method for signature 'DataDistribution,ContinuousPrior,numeric' posterior(dist, prior, x1, n1, ...) ## S4 method for signature 'DataDistribution,PointMassPrior,numeric' posterior(dist, prior, x1, n1, ...)
posterior(dist, prior, x1, n1, ...) ## S4 method for signature 'DataDistribution,ContinuousPrior,numeric' posterior(dist, prior, x1, n1, ...) ## S4 method for signature 'DataDistribution,PointMassPrior,numeric' posterior(dist, prior, x1, n1, ...)
dist |
a univariate |
prior |
a |
x1 |
stage-one test statistic |
n1 |
stage-one sample size |
... |
further optional arguments |
Object of class Prior
tmp <- ContinuousPrior(function(x) dunif(x, .2, .4), c(.2, .4)) posterior(Normal(), tmp, 2, 20) posterior(Normal(), PointMassPrior(0, 1), 2, 20)
tmp <- ContinuousPrior(function(x) dunif(x, .2, .4), c(.2, .4)) posterior(Normal(), tmp, 2, 20) posterior(Normal(), PointMassPrior(0, 1), 2, 20)
predictive_cdf()
evaluates the predictive CDF of the model specified
by a DataDistribution
dist
and
Prior
at the given stage-one outcome.
predictive_cdf(dist, prior, x1, n1, ...) ## S4 method for signature 'DataDistribution,ContinuousPrior,numeric' predictive_cdf( dist, prior, x1, n1, k = 10 * (prior@support[2] - prior@support[1]) + 1, ... ) ## S4 method for signature 'DataDistribution,PointMassPrior,numeric' predictive_cdf(dist, prior, x1, n1, ...)
predictive_cdf(dist, prior, x1, n1, ...) ## S4 method for signature 'DataDistribution,ContinuousPrior,numeric' predictive_cdf( dist, prior, x1, n1, k = 10 * (prior@support[2] - prior@support[1]) + 1, ... ) ## S4 method for signature 'DataDistribution,PointMassPrior,numeric' predictive_cdf(dist, prior, x1, n1, ...)
dist |
a univariate |
prior |
a |
x1 |
stage-one test statistic |
n1 |
stage-one sample size |
... |
further optional arguments |
k |
number of pivots for crude integral approximation |
numeric
, value of the predictive CDF
tmp <- ContinuousPrior(function(x) dunif(x, .2, .4), c(.2, .4)) predictive_cdf(Normal(), tmp, 2, 20) predictive_cdf(Normal(), PointMassPrior(.0, 1), 0, 20) # .5
tmp <- ContinuousPrior(function(x) dunif(x, .2, .4), c(.2, .4)) predictive_cdf(Normal(), tmp, 2, 20) predictive_cdf(Normal(), PointMassPrior(.0, 1), 0, 20) # .5
predictive_pdf()
evaluates the predictive PDF of the model specified
by a DataDistribution
dist
and
Prior
at the given stage-one outcome.
predictive_pdf(dist, prior, x1, n1, ...) ## S4 method for signature 'DataDistribution,ContinuousPrior,numeric' predictive_pdf( dist, prior, x1, n1, k = 10 * (prior@support[2] - prior@support[1]) + 1, ... ) ## S4 method for signature 'DataDistribution,PointMassPrior,numeric' predictive_pdf(dist, prior, x1, n1, ...)
predictive_pdf(dist, prior, x1, n1, ...) ## S4 method for signature 'DataDistribution,ContinuousPrior,numeric' predictive_pdf( dist, prior, x1, n1, k = 10 * (prior@support[2] - prior@support[1]) + 1, ... ) ## S4 method for signature 'DataDistribution,PointMassPrior,numeric' predictive_pdf(dist, prior, x1, n1, ...)
dist |
a univariate |
prior |
a |
x1 |
stage-one test statistic |
n1 |
stage-one sample size |
... |
further optional arguments |
k |
number of pivots for crude integral approximation |
numeric
, value of the predictive PDF
tmp <- ContinuousPrior(function(x) dunif(x, .2, .4), c(.2, .4)) predictive_pdf(Normal(), tmp, 2, 20) predictive_pdf(Normal(), PointMassPrior(.3, 1), 1.5, 20) # ~.343
tmp <- ContinuousPrior(function(x) dunif(x, .2, .4), c(.2, .4)) predictive_pdf(Normal(), tmp, 2, 20) predictive_pdf(Normal(), PointMassPrior(.3, 1), 1.5, 20) # ~.343
Printing an optimization result
print(x, ...)
print(x, ...)
x |
object to print |
... |
further arguments passed form other methods |
A Prior
object represents a prior distribution on the single model
parameter of a DataDistribution
class
object.
Together a prior and data-distribution specify the class of the joint
distribution of the test statisic, X, and its parameter, theta.
Currently, adoptr only allows simple models with a single parameter.
Implementations for PointMassPrior and ContinuousPrior are available.
For an example on working with priors, see here.
For the available methods, see bounds
,
expectation
, condition
, predictive_pdf
,
predictive_cdf
, posterior
disc_prior <- PointMassPrior(c(0.1, 0.25), c(0.4, 0.6)) cont_prior <- ContinuousPrior( pdf = function(x) dnorm(x, mean = 0.3, sd = 0.2), support = c(-2, 3) )
disc_prior <- PointMassPrior(c(0.1, 0.25), c(0.4, 0.6)) cont_prior <- ContinuousPrior( pdf = function(x) dnorm(x, mean = 0.3, sd = 0.2), support = c(-2, 3) )
probability_density_function
evaluates the probability density
function of a specific distribution dist
at a point x
.
probability_density_function(dist, x, n, theta, ...) ## S4 method for signature 'Binomial,numeric,numeric,numeric' probability_density_function(dist, x, n, theta, ...) ## S4 method for signature 'ChiSquared,numeric,numeric,numeric' probability_density_function(dist, x, n, theta, ...) ## S4 method for signature 'NestedModels,numeric,numeric,numeric' probability_density_function(dist, x, n, theta, ...) ## S4 method for signature 'Normal,numeric,numeric,numeric' probability_density_function(dist, x, n, theta, ...) ## S4 method for signature 'Student,numeric,numeric,numeric' probability_density_function(dist, x, n, theta, ...) ## S4 method for signature 'Survival,numeric,numeric,numeric' probability_density_function(dist, x, n, theta, ...)
probability_density_function(dist, x, n, theta, ...) ## S4 method for signature 'Binomial,numeric,numeric,numeric' probability_density_function(dist, x, n, theta, ...) ## S4 method for signature 'ChiSquared,numeric,numeric,numeric' probability_density_function(dist, x, n, theta, ...) ## S4 method for signature 'NestedModels,numeric,numeric,numeric' probability_density_function(dist, x, n, theta, ...) ## S4 method for signature 'Normal,numeric,numeric,numeric' probability_density_function(dist, x, n, theta, ...) ## S4 method for signature 'Student,numeric,numeric,numeric' probability_density_function(dist, x, n, theta, ...) ## S4 method for signature 'Survival,numeric,numeric,numeric' probability_density_function(dist, x, n, theta, ...)
dist |
a univariate |
x |
outcome |
n |
sample size |
theta |
distribution parameter |
... |
further optional arguments |
If the distribution is Binomial
,
theta denotes the rate difference between
intervention and control group.
Then, the mean is assumed to be
√ n theta.
If the distribution is Normal
, then
the mean is assumed to be
√ n theta.
value of the probability density function at point x
.
probability_density_function(Binomial(.2, FALSE), 1, 50, .3) probability_density_function(Pearson2xK(3), 1, 30, get_tau_Pearson2xK(c(0.3, 0.4, 0.7, 0.2))) probability_density_function(ZSquared(TRUE), 1, 35, get_tau_ZSquared(0.4, 1)) probability_density_function(ANOVA(3), 1, 30, get_tau_ANOVA(c(0.3, 0.4, 0.7, 0.2))) probability_density_function(Normal(), 1, 50, .3) probability_density_function(Student(TRUE), 1, 40, 1.1) probability_density_function(Survival(0.6,TRUE),0.75,50,0.9)
probability_density_function(Binomial(.2, FALSE), 1, 50, .3) probability_density_function(Pearson2xK(3), 1, 30, get_tau_Pearson2xK(c(0.3, 0.4, 0.7, 0.2))) probability_density_function(ZSquared(TRUE), 1, 35, get_tau_ZSquared(0.4, 1)) probability_density_function(ANOVA(3), 1, 30, get_tau_ANOVA(c(0.3, 0.4, 0.7, 0.2))) probability_density_function(Normal(), 1, 50, .3) probability_density_function(Student(TRUE), 1, 40, 1.1) probability_density_function(Survival(0.6,TRUE),0.75,50,0.9)
In adoptr
scores are used to assess the performance of a design.
This can be done either conditionally on the observed stage-one outcome
or unconditionally.
Consequently, score objects are either of class ConditionalScore
or
UnconditionalScore
.
expected(s, data_distribution, prior, ...) ## S4 method for signature 'ConditionalScore' expected(s, data_distribution, prior, label = NA_character_, ...) evaluate(s, design, ...) ## S4 method for signature 'IntegralScore,TwoStageDesign' evaluate(s, design, optimization = FALSE, subdivisions = 10000L, ...)
expected(s, data_distribution, prior, ...) ## S4 method for signature 'ConditionalScore' expected(s, data_distribution, prior, label = NA_character_, ...) evaluate(s, design, ...) ## S4 method for signature 'IntegralScore,TwoStageDesign' evaluate(s, design, optimization = FALSE, subdivisions = 10000L, ...)
s |
|
data_distribution |
|
prior |
a |
... |
further optional arguments |
label |
object label (string) |
design |
object |
optimization |
logical, if |
subdivisions |
maximal number of subdivisions when evaluating an integral score using adaptive quadrature (optimization = FALSE) |
All scores can be evaluated on a design using the evaluate
method.
Note that evaluate
requires a third argument x1
for
conditional scores (observed stage-one outcome).
Any ConditionalScore
can be converted to a UnconditionalScore
by forming its expected value using expected
.
The returned unconditional score is of class IntegralScore
.
No return value. Generic description of class Score
.
ConditionalPower
, ConditionalSampleSize
,
composite
design <- TwoStageDesign( n1 = 25, c1f = 0, c1e = 2.5, n2 = 50, c2 = 1.96, order = 7L ) prior <- PointMassPrior(.3, 1) # conditional cp <- ConditionalPower(Normal(), prior) expected(cp, Normal(), prior) evaluate(cp, design, x1 = .5) # unconditional power <- Power(Normal(), prior) evaluate(power, design) evaluate(power, design, optimization = TRUE) # use non-adaptive quadrature
design <- TwoStageDesign( n1 = 25, c1f = 0, c1e = 2.5, n2 = 50, c2 = 1.96, order = 7L ) prior <- PointMassPrior(.3, 1) # conditional cp <- ConditionalPower(Normal(), prior) expected(cp, Normal(), prior) evaluate(cp, design, x1 = .5) # unconditional power <- Power(Normal(), prior) evaluate(power, design) evaluate(power, design, optimization = TRUE) # use non-adaptive quadrature
simulate
allows to draw samples from a given
TwoStageDesign
.
## S4 method for signature 'TwoStageDesign,numeric' simulate(object, nsim, dist, theta, seed = NULL, ...)
## S4 method for signature 'TwoStageDesign,numeric' simulate(object, nsim, dist, theta, seed = NULL, ...)
object |
|
nsim |
number of simulation runs |
dist |
data distribution |
theta |
location parameter of the data distribution |
seed |
random seed |
... |
further optional arguments |
simulate()
returns a data.frame
with nsim
rows and for each row (each simulation run) the following columns
theta: The effect size
n1: First-stage sample size
c1f: Stopping for futility boundary
c1e: Stopping for efficacy boundary
x1: First-stage outcome
n2: Resulting second-stage sample size after observing x1
c2: Resulting second-stage decision-boundary after observing x1
x2: Second-stage outcome
reject: Decision whether the null hypothesis is rejected or not
design <- TwoStageDesign(25, 0, 2, 25, 2, order = 5) # draw samples assuming two-armed design simulate(design, 10, Normal(), .3, 42)
design <- TwoStageDesign(25, 0, 2, 25, 2, order = 5) # draw samples assuming two-armed design simulate(design, 10, Normal(), .3, 42)
Implements exact t-distributions instead of a normal approximation
Student(two_armed = TRUE) ## S4 method for signature 'Student' quantile(x, probs, n, theta, ...) ## S4 method for signature 'Student,numeric' simulate(object, nsim, n, theta, seed = NULL, ...)
Student(two_armed = TRUE) ## S4 method for signature 'Student' quantile(x, probs, n, theta, ...) ## S4 method for signature 'Student,numeric' simulate(object, nsim, n, theta, seed = NULL, ...)
two_armed |
logical indicating if a two-armed trial is regarded |
x |
outcome |
probs |
vector of probabilities |
n |
sample size |
theta |
distribution parameter |
... |
further optional arguments |
object |
object of class |
nsim |
number of simulation runs |
seed |
random seed |
see probability_density_function
and
cumulative_distribution_function
to evaluate the pdf
and the cdf, respectively.
datadist <- Student(two_armed = TRUE)
datadist <- Student(two_armed = TRUE)
subject_to(...)
can be used to generate an object of class
ConstraintsCollection
from an arbitrary number of (un)conditional
constraints.
subject_to(...) ## S4 method for signature 'ConstraintsCollection,TwoStageDesign' evaluate(s, design, optimization = FALSE, ...)
subject_to(...) ## S4 method for signature 'ConstraintsCollection,TwoStageDesign' evaluate(s, design, optimization = FALSE, ...)
... |
either constraint objects (for |
s |
object of class |
design |
object |
optimization |
logical, if |
an object of class ConstraintsCollection
subject_to
is intended to be used for constraint
specification the constraints in minimize
.
# define type one error rate and power toer <- Power(Normal(), PointMassPrior(0.0, 1)) power <- Power(Normal(), PointMassPrior(0.4, 1)) # create constrain collection subject_to( toer <= 0.025, power >= 0.9 )
# define type one error rate and power toer <- Power(Normal(), PointMassPrior(0.0, 1)) power <- Power(Normal(), PointMassPrior(0.4, 1)) # create constrain collection subject_to( toer <= 0.025, power >= 0.9 )
Implements the normal approximation of the log-rank test statistic.
Survival(event_rate, two_armed = TRUE) ## S4 method for signature 'Survival' quantile(x, probs, n, theta, ...) ## S4 method for signature 'Survival,numeric' simulate(object, nsim, n, theta, seed = NULL, ...)
Survival(event_rate, two_armed = TRUE) ## S4 method for signature 'Survival' quantile(x, probs, n, theta, ...) ## S4 method for signature 'Survival,numeric' simulate(object, nsim, n, theta, seed = NULL, ...)
event_rate |
probability that a subject will eventually have an event |
two_armed |
logical indicating if a two-armed trial is regarded |
x |
outcome |
probs |
vector of probabilities |
n |
sample size |
theta |
distribution parameter |
... |
further optional arguments |
object |
object of class |
nsim |
number of simulation runs |
seed |
random seed |
event_rate
cf. parameter 'event_rate'
see probability_density_function
and
cumulative_distribution_function
to evaluate the pdf
and the cdf, respectively.
datadist <- Survival(event_rate=0.6, two_armed=TRUE)
datadist <- Survival(event_rate=0.6, two_armed=TRUE)
SurvivalDesign
is a function that converts an arbitrary design to a survival design.
SurvivalDesign(design, event_rate) ## S4 method for signature 'TwoStageDesign' SurvivalDesign(design, event_rate) ## S4 method for signature 'TwoStageDesign' TwoStageDesign(n1, event_rate) ## S4 method for signature 'OneStageDesign' OneStageDesign(n, event_rate) ## S4 method for signature 'OneStageDesign' SurvivalDesign(design, event_rate) ## S4 method for signature 'GroupSequentialDesign' GroupSequentialDesign(n1, event_rate) ## S4 method for signature 'GroupSequentialDesign' SurvivalDesign(design, event_rate)
SurvivalDesign(design, event_rate) ## S4 method for signature 'TwoStageDesign' SurvivalDesign(design, event_rate) ## S4 method for signature 'TwoStageDesign' TwoStageDesign(n1, event_rate) ## S4 method for signature 'OneStageDesign' OneStageDesign(n, event_rate) ## S4 method for signature 'OneStageDesign' SurvivalDesign(design, event_rate) ## S4 method for signature 'GroupSequentialDesign' GroupSequentialDesign(n1, event_rate) ## S4 method for signature 'GroupSequentialDesign' SurvivalDesign(design, event_rate)
design |
design that should be converted to a survival design |
event_rate |
probability that a subject in either group will eventually have an event |
n1 |
design object to convert (overloaded from |
n |
design object to convert (overloaded from |
Converts any type of design to a survival design
design <- get_initial_design(0.4, 0.025, 0.1) SurvivalDesign(design, 0.8) design_os <- get_initial_design(0.4, 0.025, 0.1, type_design = "one-stage") design_gs <- get_initial_design(0.4, 0.025, 0.1, type_design = "group-sequential") OneStageDesign(design_os, 0.7) GroupSequentialDesign(design_gs, 0.8)
design <- get_initial_design(0.4, 0.025, 0.1) SurvivalDesign(design, 0.8) design_os <- get_initial_design(0.4, 0.025, 0.1, type_design = "one-stage") design_gs <- get_initial_design(0.4, 0.025, 0.1, type_design = "group-sequential") OneStageDesign(design_os, 0.7) GroupSequentialDesign(design_gs, 0.8)
Get tunable parameters of a design as numeric vector via
tunable_parameters
or update
a design object with a suitable
vector of values for its tunable parameters.
tunable_parameters(object, ...) ## S4 method for signature 'TwoStageDesign' tunable_parameters(object, ...) ## S4 method for signature 'TwoStageDesign' update(object, params, ...) ## S4 method for signature 'OneStageDesign' update(object, params, ...)
tunable_parameters(object, ...) ## S4 method for signature 'TwoStageDesign' tunable_parameters(object, ...) ## S4 method for signature 'TwoStageDesign' update(object, params, ...) ## S4 method for signature 'OneStageDesign' update(object, params, ...)
object |
|
... |
further optional arguments |
params |
vector of design parameters, must be in same order as returned
by |
The tunable
slot of a TwoStageDesign
stores information about
the set of design parameters which are considered fixed (not changed during
optimization) or tunable (changed during optimization).
For details on how to fix certain parameters or how to make them tunable
again, see make_fixed
and make_tunable
.
tunable_parameters
returns the numerical values of all
tunable parameters as a vector.
update
returns the updated design.
design <- TwoStageDesign(25, 0, 2, 25, 2, order = 5) tunable_parameters(design) design2 <- update(design, tunable_parameters(design) + 1) tunable_parameters(design2)
design <- TwoStageDesign(25, 0, 2, 25, 2, order = 5) tunable_parameters(design) design2 <- update(design, tunable_parameters(design) + 1) tunable_parameters(design2)
TwoStageDesign
is the fundamental design class of the
adoptr package.
Formally, we represent a generic two-stage design as a five-tuple
(n1, c1f, c1e, n2(·), c2(·)).
Here, n1 is the first-stage sample
size (per group), c1f
and c1e are
boundaries for early stopping for futility and efficacy, respectively.
Since the trial design is a two-stage design, the elements
n2(·) (stage-two sample
size) and c2(·)
(stage-two critical value) are functions of the first-stage outcome
X1=x1.
X1 denotes the first-stage test
statistic. A brief description on this definition of two-stage designs can be
read here.
For available methods, see the 'See Also' section at the end of this page.
TwoStageDesign(n1, ...) ## S4 method for signature 'numeric' TwoStageDesign( n1, c1f, c1e, n2_pivots, c2_pivots, order = NULL, event_rate, ... ) ## S4 method for signature 'TwoStageDesign' summary(object, ..., rounded = TRUE)
TwoStageDesign(n1, ...) ## S4 method for signature 'numeric' TwoStageDesign( n1, c1f, c1e, n2_pivots, c2_pivots, order = NULL, event_rate, ... ) ## S4 method for signature 'TwoStageDesign' summary(object, ..., rounded = TRUE)
n1 |
stage-one sample size |
... |
further optional arguments |
c1f |
early futility stopping boundary |
c1e |
early efficacy stopping boundary |
n2_pivots |
numeric vector, stage-two sample size on the integration pivot points |
c2_pivots |
numeric vector, stage-two critical values on the integration pivot points |
order |
|
event_rate |
probability that a subject in either group will eventually have an event, only needs to be specified for time-to-event endpoints |
object |
object to show |
rounded |
should rounded n-values be used? |
summary
can be used to quickly compute and display basic facts about
a TwoStageDesign.
An arbitrary number of names UnconditionalScore
objects can be
provided via the optional arguments ...
and are included in the summary displayed using
print
.
n1
cf. parameter 'n1'
c1f
cf. parameter 'c1f'
c1e
cf. parameter 'c1e'
n2_pivots
vector of length 'order' giving the values of n2 at the pivot points of the numeric integration rule
c2_pivots
vector of length order giving the values of c2 at the pivot points of the numeric integration rule
x1_norm_pivots
normalized pivots for integration rule (in [-1, 1])
the actual pivots are scaled to the interval [c1f, c1e] and can be
obtained by the internal method adoptr:::scaled_integration_pivots(design)
weights
weights of of integration rule at x1_norm_pivots
for
approximating integrals over x1
tunable
named logical vector indicating whether corresponding slot is
considered a tunable parameter (i.e. whether it can be changed during
optimization via minimize
or not; cf. make_fixed
)
For accessing sample sizes and critical values safely, see methods in
n
and c2
; for modifying behaviour during optimizaton
see make_tunable
; to convert between S4 class represenation and
numeric vector, see tunable_parameters
; for simulating from a given
design, see simulate
;
for plotting see plot,TwoStageDesign-method
.
Both group-sequential and
one-stage designs (!) are implemented as subclasses of
TwoStageDesign
.
design <- TwoStageDesign(50, 0, 2, 50.0, 2.0, 5) pow <- Power(Normal(), PointMassPrior(.4, 1)) summary(design, "Power" = pow)
design <- TwoStageDesign(50, 0, 2, 50.0, 2.0, 5) pow <- Power(Normal(), PointMassPrior(.4, 1)) summary(design, "Power" = pow)
When conducting a study with time-to-event endpoints, the main interest is not the
sample size, but the number of overall necessary events. Thus, adoptr does not use
the sample size for calculating the design. Instead,
it uses the number of events directly.
In the framework of adoptr, all the calculations are done group-wise, where both of the groups are equal-sized.
This means, that the number of events adoptr has computed is only half of the overall number of necessary events.
In order to facilitate this issue, the look of the
summary
and show
functions have been changed in the survival analysis setting.
The sample size is implicitly determined
by dividing the number of events by the event rate. Survival objects are only
created, when the argument event_rate
is not missing.
event_rate
probability that a subject in either group will eventually have an event
TwoStageDesign
for superclass and inherited methods
Implementation of , where
is normally distributed with mean
and variance
.
is chi-squared distributed
with
degree of freedom and non-centrality parameter
.
The function
get_tau_ZSquared
computes the factor ,
such that
is the equivalent of
in the normally
distributed case. The square of a normal distribution
can be used
for two-sided hypothesis testing.
ZSquared(two_armed = TRUE) get_tau_ZSquared(mu, sigma)
ZSquared(two_armed = TRUE) get_tau_ZSquared(mu, sigma)
two_armed |
logical indicating if a two-armed trial is regarded |
mu |
mean of Z |
sigma |
standard deviation of Z |
zsquared <- ZSquared(FALSE) H1 <- PointMassPrior(get_tau_ZSquared(0.4, 1), 1)
zsquared <- ZSquared(FALSE) H1 <- PointMassPrior(get_tau_ZSquared(0.4, 1), 1)