PowerTOST • Dose-Proportionality

 
library(PowerTOST) # attach the library

Defaults

Parameter Argument Purpose Default
\(\alpha\) alpha Nominal level of the test 0.05
CV CV CV none
doses doses Vector of doses see examples
\(\pi\) targetpower Minimum desired power 0.80
\(\beta_{0}\) beta0 ‘True’ or assumed slope of the power model see below
\(\theta_{1}\) theta1 Lower limit for the ratio of dose normalized means Rdmn see below
\(\theta_{2}\) theta2 Upper limit for the ratio of dose normalized means Rdmn see below
design design Planned design "crossover"
dm dm Design matrix NULL
CVb CVb Coefficient of variation of the between-subject variability
print print Show information in the console? TRUE
details details Show details of the sample size search? FALSE
imax imax Maximum number of iterations 100

Arguments targetpower, theta1, theta2, and CV have to be given as fractions, not percent.
The CV is generally the within-subject coefficient of variation. Only for design = "parallel" it is the total (a.k.a. pooled) CV. The between-subject coefficient of variation CVb is only neccessary if design = "IBD" (if missing, it will be set to 2*CV).

The ‘true’ or assumed slope of the power model \(\beta_{0}\) defaults to 1+log(0.95)/log(rd), where rd is the ratio of the highest/lowest dose.

Supported designs are "crossover" (default; Latin Squares), "parallel", and "IBD" (incomplete block design). Note that when "crossover" is chosen, instead of Latin Squares any Williams’ design could be used as well (identical degrees of freedom result in the same sample size).

With sampleN.dp(..., details = FALSE, print = FALSE) results are provided as a data.frame with ten (design = "crossover") or eleven (design = "parallel" or design = "IBD") columns: Design, alpha, CV, (CVb,) doses, beta0, theta1, theta2, Sample size, Achieved power, and Target power. To access e.g., the sample size use sampleN.dp[["Sample size"]].

The estimated sample size gives always the total number of subjects (not subject/sequence in crossovers or subjects/group in parallel designs).

Examples

Estimate the sample size for a modified Fibonacci dose-escalation study, lowest dose 10, three levels. Assumed CV 0.20 and \(\beta_{0}\) slightly higher than 1. Defaults employed.

mod.fibo <- function(lowest, levels) {
  # modified Fibonacci dose-escalation
  fib      <- c(2, 1 + 2/3, 1.5, 1 + 1/3)
  doses    <- numeric(levels)
  doses[1] <- lowest
  level    <- 2
  repeat {
    if (level <= 4) {
      doses[level] <- doses[level-1] * fib[level-1]
    } else {  # ratio 1.33 for all higher doses
      doses[level] <- doses[level-1] * fib[4]
    }
    level <- level + 1
    if (level > levels) {
      break
    }
  }
  return(signif(doses, 3))
}
lowest <- 10
levels <- 3
doses  <- mod.fibo(lowest, levels)
sampleN.dp(CV = 0.20, doses = doses, beta0 = 1.02)
# 
# ++++ Dose proportionality study, power model ++++
#             Sample size estimation
# -------------------------------------------------
# Study design: crossover (3x3 Latin square) 
# alpha = 0.05, target power = 0.8
# Equivalence margins of R(dnm) = 0.8 ... 1.25 
# Doses = 10 20 33.3 
# True slope = 1.02, CV = 0.2
# Slope acceptance range = 0.81451 ... 1.1855 
# 
# Sample size (total)
#  n     power
# 15   0.808127

As above but with an additional level.

levels <- 4
doses  <- mod.fibo(lowest, levels)
x <- sampleN.dp(CV = 0.20, doses = doses, beta0 = 1.02) # we need the data.frame later
# 
# ++++ Dose proportionality study, power model ++++
#             Sample size estimation
# -------------------------------------------------
# Study design: crossover (4x4 Latin square) 
# alpha = 0.05, target power = 0.8
# Equivalence margins of R(dnm) = 0.8 ... 1.25 
# Doses = 10 20 33.3 50 
# True slope = 1.02, CV = 0.2
# Slope acceptance range = 0.86135 ... 1.1386 
# 
# Sample size (total)
#  n     power
# 16   0.867441

Note that with the wider dose range the acceptance range narrows.

Explore the impact of dropouts.

res <- data.frame(n = seq(x[["Sample size"]], 12, -1),
                  power = NA)
for (i in 1:nrow(res)) {
  res$power[i] <- signif(suppressMessages(
                           power.dp(CV = 0.20, doses = doses,
                                    beta0 = 1.02,
                                    n = res$n[i])), 5)
}
res <- res[res$power >= 0.80, ]
print(res, row.names = FALSE)
#   n   power
#  16 0.86744
#  15 0.82914
#  14 0.81935
#  13 0.81516

As usual nothing to worry about.

Rather extreme: Five levels, but we want only three periods. Hence, we opt for an incomplete block design. The design matrix of a balanced minimal repeated measurements design is obtained by the function balmin.RMD() of package crossdes.

levels <- 5
doses  <- mod.fibo(lowest, levels)
per    <- 3
block  <- levels*(levels-1)/(per-1)
dm     <- crossdes::balmin.RMD(levels, block, per)
x      <- sampleN.dp(CV = 0.20, doses = doses, beta0 = 1.02,
                     design = "IBD", dm = dm)
# 
# ++++ Dose proportionality study, power model ++++
#             Sample size estimation
# -------------------------------------------------
# Study design: IBD (5x10x3) 
# alpha = 0.05, target power = 0.8
# Equivalence margins of R(dnm) = 0.8 ... 1.25 
# Doses = 10 20 33.3 50 66.7 
# True slope = 1.02, CV = 0.2, CVb = 0.4
# Slope acceptance range = 0.88241 ... 1.1176 
# 
# Sample size (total)
#  n     power
# 30   0.898758

The IBD comes with a price since we need at least two blocks.

res <- data.frame(n = seq(x[["Sample size"]], nrow(dm), -1),
                  power = NA)
for (i in 1:nrow(res)) {
  res$power[i] <- signif(suppressMessages(
                           power.dp(CV = 0.20, doses = doses,
                                    beta0 = 1.02, design = "IBD",
                                    dm = dm, n = res$n[i])), 5)
}
res <- res[res$power >= 0.80, ]
print(res, row.names = FALSE)
#   n   power
#  30 0.89876
#  29 0.89196
#  28 0.87939
#  27 0.87201
#  26 0.85793
#  25 0.83587
#  24 0.82470
#  23 0.80405

Again, we don’t have to worry about dropouts.

For a wide dose range the acceptance range narrows and becomes increasingly difficult to meet.

doses  <- 2^(seq(0, 8, 2))
levels <- length(doses)
sampleN.dp(CV = 0.30, doses = doses, beta0 = 1.02,
           design = "crossover")
# 
# ++++ Dose proportionality study, power model ++++
#             Sample size estimation
# -------------------------------------------------
# Study design: crossover (5x5 Latin square) 
# alpha = 0.05, target power = 0.8
# Equivalence margins of R(dnm) = 0.8 ... 1.25 
# Doses = 1 4 16 64 256 
# True slope = 1.02, CV = 0.3
# Slope acceptance range = 0.95976 ... 1.0402 
# 
# Sample size (total)
#  n     power
# 70   0.809991

In an exploratory setting more liberal limits could be specified (only one has to be specified; the other is calculated as the reciprocal of it).

sampleN.dp(CV = 0.30, doses = doses, beta0 = 1.02,
           design = "crossover", theta1 = 0.75)
# 
# ++++ Dose proportionality study, power model ++++
#             Sample size estimation
# -------------------------------------------------
# Study design: crossover (5x5 Latin square) 
# alpha = 0.05, target power = 0.8
# Equivalence margins of R(dnm) = 0.75 ... 1.333333 
# Doses = 1 4 16 64 256 
# True slope = 1.02, CV = 0.3
# Slope acceptance range = 0.94812 ... 1.0519 
# 
# Sample size (total)
#  n     power
# 30   0.828246

Hummel et al.1 proposed even more liberal {\(\theta_{1},\theta_{2}\)} of {0.50, 2.0}.

Cave!

There is no guarantee that a desired incomplete block design (for given dose levels and number of periods) can be constructed. If you provide your own design matrix (in the argument dm) it is not assessed for meaningfulness.

Author

Detlew Labes

Man-pages

Man-pages of functions used in this vignette:

Online manual of all functions.

License

Helmut Schütz 2019-12-19

GPL-2 | GPL-3


  1. Hummel J, McKendrick S, Brindley C, French R. Exploratory assessment of dose proportionality: review of current approaches and proposal for a practical criterion. Pharm. Stat. 2009; 8(1): 38–49. doi:10.1002/pst.326.