Parameter  Argument  Purpose  Default 

\(\alpha\)  alpha 
Nominal level of the test  0.025 
\(\pi\)  targetpower 
Minimum desired power  0.80 
logscale  logscale 
Analysis on logtransformed or original scale?  TRUE 
margin  margin 
Noninferiority margin  see below 
\(\theta_{0}\)  theta0 
‘True’ or assumed T/R ratio  see below 
CV  CV 
CV  none 
design  design 
Planned design  "2x2" 
imax  imax 
Maximum number of iterations  100 
print 
Show information in the console?  TRUE 

details  details 
Show details of the sample size search?  FALSE 
Note that contrary to the other functions of the package a onesided ttest (instead of TOST) is employed. Hence, \(\alpha\) defaults to 0.025.
Defaults depending on the argument logscale
:
Parameter  Argument  logscale=TRUE 
logscale=FALSE 

margin  margin 
0.80 
–0.20 
\(\theta_{0}\)  theta0 
0.95 
+0.05 
Arguments targetpower
, margin
, theta0
, and CV
have to be given as fractions, not percent.
The CV is generally the withinsubject coefficient of variation. Only for design = "parallel"
it is the total (a.k.a. pooled) CV.
Designs with one (parallel), two (conventional crossover and paired), and three or four periods (replicates) are supported.
# design name df
# "parallel" 2 parallel groups n2
# "2x2" 2x2 crossover n2
# "2x2x2" 2x2x2 crossover n2
# "2x2x3" 2x2x3 replicate crossover 2n3
# "2x2x4" 2x2x4 replicate crossover 3n4
# "2x4x4" 2x4x4 replicate crossover 3n4
# "2x3x3" partial replicate (2x3x3) 2n3
# "2x4x2" Balaam’s (2x4x2) n2
# "2x2x2r" Liu’s 2x2x2 repeated xover 3n2
# "paired" paired means n1
The terminology of the design
argument follows this pattern: treatments x sequences x periods
. The conventional TRRT (a.k.a. ABBA) design can be abbreviated as "2x2"
. Some call the "parallel"
design a ‘onesequence’ design. The design "paired"
has two periods but no sequences, e.g., in studying linear pharmacokinetics a single dose is followed by multiple doses. A profile in steady state (T) is compared to the one after the single dose (R). Note that the underlying model assumes no period effects.
With sampleN.noninf(..., details = FALSE, print = FALSE)
results are provided as a data.frame with eight columns Design
, alpha
, CV
, theta0
, Margin
, Sample size
, Achieved power
, and Target power
. To access e.g., the sample size use either sampleN.noninf[1, 6]
or sampleN.noninf[["Sample size"]]
. We suggest to use the latter in your code for clarity.
The estimated sample size gives always the total number of subjects (not subject/sequence in crossovers or subjects/group in parallel designs).
If the supplied margin is < 1 (logscale = TRUE
) or < 0 (logscale = FALSE
), then it is assumed that higher response values are better. The hypotheses are
logscale = TRUE
\[H_{0}:\theta_0 \leq \log({margin})\:vs\:H_{1}:\theta_0>\log({margin})\] where \(\theta_0=\mu_T/\mu_R\)
logscale = FALSE
\[H_{0}:\theta_0 \leq {margin}\:vs\:H_{1}:\theta_0>{margin}\]
where \(\theta_0=\mu_T\mu_R\)
Estimate the sample size for assumed intrasubject CV 0.25. Defaults margin
0.80 and \(\theta_{0}\) 0.95 employed.
sampleN.noninf(CV = 0.25)
#
# ++++++++++++ Noninferiority test +++++++++++++
# Sample size estimation
# 
# Study design: 2x2 crossover
# logtransformed data (multiplicative model)
#
# alpha = 0.025, target power = 0.8
# Noninf. margin = 0.8
# True ratio = 0.95, CV = 0.25
#
# Sample size (total)
# n power
# 36 0.820330
To get only the sample size:
Note that the sample size is always rounded up to give balanced sequences (here a multiple of two). Since power is higher than our target, likely this was the case here. Let us check that.
Which power will we get with a sample size of 35?
Confirmed that with 35 subjects we will already reach the target power. That means also that one dropout will not compromise power.
If the supplied margin is > 1 (logscale = TRUE
) or > 0 (logscale = FALSE
), then it is assumed that lower response values are better. The hypotheses are
logscale = TRUE
\[H_{0}:\theta_0 \geq \log({margin})\:vs\:H_{1}:\theta_0<\log({margin})\] where \(\theta_0=\mu_T/\mu_R\)
logscale = FALSE
\[H_{0}:\theta_0 \geq {margin}\:vs\:H_{1}:\theta_0<{margin}\]
where \(\theta_0=\mu_T\mu_R\)
Estimate the sample size for assumed intrasubject CV 0.25.
sampleN.noninf(CV = 0.25, margin = 1.25, theta0 = 1/0.95)
#
# ++++++++++++ Nonsuperiority test +++++++++++++
# Sample size estimation
# 
# Study design: 2x2 crossover
# logtransformed data (multiplicative model)
#
# alpha = 0.025, target power = 0.8
# Noninf. margin = 1.25
# True ratio = 1.052632, CV = 0.25
#
# Sample size (total)
# n power
# 36 0.820330
Same sample size like in example 1 since reciprocal values of both margin
0.80 and \(\theta_{0}\) are specified.
Compare a new modified release formulation (regimen once a day) with an intermediate release formulation (twice a day).^{1} C_{min} is the target metric for efficacy (noninferiority) and C_{max} for safety (nonsuperiority). Margins are 0.80 for C_{min} and 1.25 for C_{max}. CVs are 0.35 for C_{min} and 0.20 for C_{max}; \(\theta_{0}\) 0.95 for C_{min} and 1.05 for C_{max}. Full replicate design due to the high variability of C_{min}.
Which PK metric leads the sample size?
res < data.frame(design = "2x2x4", metric = c("Cmin", "Cmax"),
margin = c(0.80, 1.25), CV = c(0.35, 0.20),
theta0 = c(0.95, 1.05), n = NA, power = NA)
for (i in 1:2) {
res[i, 6:7] < sampleN.noninf(design = res$design[i],
margin = res$margin[i],
theta0 = res$theta0[i],
CV = res$CV[i],
details = FALSE,
print = FALSE)[6:7]
}
print(res, row.names = FALSE)
# design metric margin CV theta0 n power
# 2x2x4 Cmin 0.80 0.35 0.95 32 0.8077926
# 2x2x4 Cmax 1.25 0.20 1.05 12 0.8406410
The sample size depends on C_{min}. Hence, the study is ‘overpowered’ for C_{max}.
Therefore, that gives us some ‘headroom’ for C_{max}.
power.noninf(design = "2x2x4", margin = 1.25, CV = 0.25,
theta0 = 1.10, n = 32) # higher CV, worse theta0
# [1] 0.8279726
The bracketing approach does not necessarily give lower sample sizes than tests for equivalence. In this example we could aim at referencescaling for the highly variable C_{min} and at conventional ABE for C_{max}.
res < data.frame(design = "2x2x4", indended = c("ABEL", "ABE"),
metric = c("Cmin", "Cmax"), CV = c(0.35, 0.20),
theta0 = c(0.90, 1.05), n = NA, power = NA,
stringsAsFactors = FALSE)
res[1, 6:7] < sampleN.scABEL(CV = res$CV[1], theta0 = res$theta0[1],
design = res$design[1], print = FALSE,
details = FALSE)[8:9]
res[2, 6:7] < sampleN.TOST(CV = res$CV[2], theta0 = res$theta0[2],
design = res$design[2], print = FALSE,
details = FALSE)[7:8]
print(res, row.names = FALSE)
# design indended metric CV theta0 n power
# 2x2x4 ABEL Cmin 0.35 0.90 34 0.8118400
# 2x2x4 ABE Cmax 0.20 1.05 10 0.8517596
Which method is optimal is a casetocase decision. Although in this example the bracketing approach seems to be the ‘winner’ (32 subjects instead of 34), we might fail if the CV of C_{min} is larger than assumed, whereas in referencescaling we might still pass due to the expanded limits.
n < sampleN.scABEL(CV = 0.35, theta0 = 0.90, design = "2x2x4",
print = FALSE, details = FALSE)[["Sample size"]]
# CV and theta0 of both metrics worse than assumed
res < data.frame(design = "2x2x4", indended = c("ABEL", "ABE"),
metric = c("Cmin", "Cmax"), CV = c(0.50, 0.25),
theta0 = c(0.88, 1.12), n = n, power = NA,
stringsAsFactors = FALSE)
res[1, 7] < power.scABEL(CV = res$CV[1], theta0 = res$theta0[1],
design = res$design[1], n = n)
res[2, 7] < power.TOST(CV = res$CV[2], theta0 = res$theta0[2],
design = res$design[2], n = n)
print(res, row.names = FALSE)
# design indended metric CV theta0 n power
# 2x2x4 ABEL Cmin 0.50 0.88 34 0.8183300
# 2x2x4 ABE Cmax 0.25 1.12 34 0.8258111
Manpages of functions used in examples of this vignette:
Online manual of all functions.
European Medicines Agency, Committee for Medicinal Products for Human Use. Guideline on the pharmacokinetic and clinical evaluation of modified release dosage forms. London, 20 November 2014. EMA/CPMP/EWP/280/96 Corr1.↩