## Power of 2 independent TOSTs ≈ 2 simultaneous TOSTs with ρ=0 [Power / Sample Size]

Hi libaiyi,

❝ And it could not be simplified as Overall power = (power of AUC0 * power of Cmax) to decrease power needed of each for the lack of ρ?

For two tests, it could.
Try this (conventional BE-limits, T/R-ratio 0.95, target power 0.8, 2×2×2 crossover):

library(PowerTOST) CV1      <- 0.3 # Cmax CV2      <- 0.2 # AUC0-t n1       <- sampleN.TOST(CV=CV1, print=FALSE)[["Sample size"]] n2       <- sampleN.TOST(CV=CV2, print=FALSE)[["Sample size"]] n        <- max(n1, n2) rho.min  <- 0.25 rho.max  <- 0.75 rho.step <- 0.25 rho      <- c(1-.Machine$double.eps, seq(rho.max, rho.min, -rho.step), .Machine$double.eps) pwr0.1   <- power.TOST(CV=CV1, n=n) pwr0.2   <- power.TOST(CV=CV2, n=n) nsims    <- 1e6 pwr1     <- numeric(length(rho)) res1     <- character(length(rho)) f        <- "%.4f" for (j in seq_along(rho)) {   pwr1[j] <- power.2TOST(CV=c(CV1, CV2), n=n, rho=rho[j], nsims=nsims)   res1[j] <- paste0("\n  rho = ", sprintf(f, rho[j]), ": ",                     sprintf(f, pwr1[j])) } res0     <- paste0("\nCV1: ", sprintf(f, CV1), ", CV2: ", sprintf(f, CV2),   "\nSample size based on max(CV1, CV2) = ", sprintf(f, max(CV1, CV2)), ": ", n,   "\nPower for two independent TOSTs",   "\n  PK metric with CV  = ", sprintf(f, CV1), ": ", sprintf(f, pwr0.1),   "\n  PK metric with CV  = ", sprintf(f, CV2), ": ", sprintf(f, pwr0.2),   "\n    overall power (p1\u00D7p2)    : ", sprintf(f, pwr0.1*pwr0.2),   "\nPower for two simultaneous TOSTs (",   formatC(nsims, digits=0, format="d", big.mark = ","), " simulations each)") cat(res0, paste0(res1), "\n")

Gives:

CV1: 0.3000, CV2: 0.2000 Sample size based on max(CV1, CV2) = 0.3000: 40 Power for two independent TOSTs   PK metric with CV  = 0.3000: 0.8158   PK metric with CV  = 0.2000: 0.9848     overall power (p1×p2)    : 0.8035 Power for two simultaneous TOSTs (1,000,000 simulations each)   rho = 1.0000: 0.8162   rho = 0.7500: 0.8151   rho = 0.5000: 0.8111   rho = 0.2500: 0.8071   rho = 0.0000: 0.8041

If ρ=1, power ~ the one by TOST of the PK metric with the higher CV. Implicitly people assume a perfect correlation when estimating the sample size based on the PK metric with the higher CV.
If ρ=0, power ~ pTOST1 × pTOST2. 证明完毕

Similar for three tests (e.g., for the FDA). Let’s assume the CV of AUC0–∞ with 0.22 to be a little bit larger than the one of AUC0–t with 0.2. Then we would get pTOST1 × pTOST2 × pTOST3 = 0.8158×0.9848×0.9660 = 0.7762. Since likely the correlation is high (esp. between AUC0–t and AUC0–∞), a relative drop in power from the desired 0.8 by less than 3% doesn’t worry me. In practice (high correlation) the loss will be negligible.

Another example. Since CV1 scratches the limit of HVD(P)s, it might be a good idea to be more cautious and assume a T/R of 0.90 (and – if you are courageous – assume a nicer one of AUC at 0.925). Let’s try a 4-period full replicate design:

library(PowerTOST) CV1      <- 0.3 # Cmax CV2      <- 0.2 # AUC design   <- "2x2x4" theta0.1 <- 0.90 theta0.2 <- 0.925 n1       <- sampleN.TOST(CV=CV1, theta0=theta0.1, design=design,                          print=FALSE)[["Sample size"]] n2       <- sampleN.TOST(CV=CV2, theta0=theta0.2, design=design,                          print=FALSE)[["Sample size"]] n        <- max(n1, n2) nsims    <- 1e6 rho.min  <- 0.25 rho.max  <- 0.75 rho.step <- 0.25 rho      <- c(1-.Machine$double.eps, seq(rho.max, rho.min, -rho.step), .Machine$double.eps) pwr0.1   <- power.TOST(CV=CV1, theta0=theta0.1, n=n, design=design) pwr0.2   <- power.TOST(CV=CV2, theta0=theta0.2, n=n, design=design) pwr1     <- numeric(length(rho)) res1     <- character(length(rho)) f        <- "%.4f" for (j in seq_along(rho)) {   pwr1[j] <- power.2TOST(CV=c(CV1, CV2), theta0=c(theta0.1, theta0.2),                          n=n, design=design, rho=rho[j], nsims=nsims)   res1[j] <- paste0("\n  rho = ", sprintf(f, rho[j]), ": ",                     sprintf(f, pwr1[j])) } res0     <- paste0("\nCV1     : ", sprintf(f, CV1),                    ", CV2     : ", sprintf(f, CV2),   "\ntheta0.1: ", sprintf(f, theta0.1), ", theta0.2: ", sprintf(f, theta0.2),   "\nSample size based on max(CV1, CV2) = ", sprintf(f, max(CV1, CV2)),   ": ", n, " (", design, " design)",   "\nPower for two independent TOSTs",   "\n  PK metric with CV  = ", sprintf(f, CV1), ": ", sprintf(f, pwr0.1),   "\n  PK metric with CV  = ", sprintf(f, CV2), ": ", sprintf(f, pwr0.2),   "\n    overall power (p1\u00D7p2)    : ", sprintf(f, pwr0.1*pwr0.2),   "\nPower for two simultaneous TOSTs (",   formatC(nsims, digits=0, format="d", big.mark = ","), " simulations each)") cat(res0, paste0(res1), "\n")

Gives:

CV1     : 0.3000, CV2     : 0.2000 theta0.1: 0.9000, theta0.2: 0.9250 Sample size based on max(CV1, CV2) = 0.3000: 40 (2x2x4 design) Power for two independent TOSTs   PK metric with CV  = 0.3000: 0.8100   PK metric with CV  = 0.2000: 0.9985     overall power (p1×p2)    : 0.8088 Power for two simultaneous TOSTs (1,000,000 simulations each)   rho = 1.0000: 0.8101   rho = 0.7500: 0.8105   rho = 0.5000: 0.8102   rho = 0.2500: 0.8096   rho = 0.0000: 0.8094

If you assume a T/R-ratio of 0.90 for both (probably better):

CV1     : 0.3000, CV2     : 0.2000 theta0.1: 0.9000, theta0.2: 0.9000 Sample size based on max(CV1, CV2) = 0.3000: 40 (2x2x4 design) Power for two independent TOSTs   PK metric with CV  = 0.3000: 0.8100   PK metric with CV  = 0.2000: 0.9819     overall power (p1×p2)    : 0.7953 Power for two simultaneous TOSTs (1,000,000 simulations each)   rho = 1.0000: 0.8101   rho = 0.7500: 0.8089   rho = 0.5000: 0.8041   rho = 0.2500: 0.7992   rho = 0.0000: 0.7958

Dif-tor heh smusma 🖖🏼 Довге життя Україна!
Helmut Schütz

The quality of responses received is directly proportional to the quality of the question asked. 🚮
Science Quotes