## Sample size and power [RSABE / ABEL]

Dear all,

The idea behind Scaled Average Bioequivalence (SABE) is to avoid extreme sample sizes required for Average Bio­equi­va­lence (ABE) while preserving power independent from the CV.

With the -script at the end you can reproduce the plots below. All with sample sizes for at least 80% power in a two-se­quence four-period full replicate design. Since Average Bio­equi­va­lence with Expanding Limits (ABEL) is less permissive than Re­fe­rence-Scaled Average Bioequivalence (RSABE) we require larger sample sizes (28–36 vs 22–32).
• Evaluation based on ABE (if $$\small{\widehat{CV}_\textrm{wR}\leq30\%}$$) or ABEL (if $$\small{\widehat{CV}_\textrm{wR}>30\%}$$).
• If by ABEL,
• limit the expansion at $$\small{\widehat{CV}_\textrm{wR}=50\%}$$ and
• impose the PE-constraint {80.00–125.00%}.

• Evaluation based on ABE (if $$\small{\widehat{s}_\textrm{wR}<0.294}$$) or RSABE (if $$\small{\widehat{s}_\textrm{wR}\ge0.294}$$). Note that $$\small{\widehat{s}_\textrm{wR}=0.294\Rightarrow \widehat{CV}_\textrm{wR}\approx 30.0469\%}$$.
• If by RSABE, impose the PE-constraint {80.00–125.00%}.

If $$\small{\widehat{CV}_\textrm{wR}}$$ is relatively small, the ABE-component is relevant. At $$\small{\widehat{CV}_\textrm{wR}\sim 30\%}$$ the chance to assess the study by ABE is $$\small{\sim 50\%}$$. When $$\small{\widehat{CV}_\textrm{wR}}$$ gets larger, the PE-constraint gets increasingly important. That’s more pronounced for RSABE because in ABEL the upper cap of scaling is relevant as well.

library(PowerTOST) design <- "2x2x4" target <- 0.8 theta0 <- 0.9 CV     <- seq(0.3, 0.65, 0.0005) # Cave: Long runtime with such a small step size # 'Pure' SABE for comparison: No upper cup of scaling, no PE constraint # ABEL modified pure1  <- reg_const("USER", r_const = 0.76, CVswitch = 0.3, CVcap = Inf) # RSABE modified pure2  <- reg_const("USER", r_const = log(1.25)/0.25, CVswitch = 0.3, CVcap = Inf) pure1$pe_constr <- pure2$pe_constr <- FALSE pure1$est_method <- "ANOVA" pure2$est_method <- "ISC" # Defaults: theta0 = 0.9, targetpower = 0.8 res1   <- res2 <- data.frame(CV = CV, n = NA_integer_, overall = NA_real_,                              PE = NA_real_, ABE = NA_real_, SABE = NA_real_) pb     <- txtProgressBar(0, 1, 0, char = "\u2588", width = NA, style = 3) for (i in seq_along(CV)) {   tmp           <- sampleN.scABEL(CV = CV[i], design = design,                                   theta0 = theta0, targetpower = target,                                   details = FALSE, print = FALSE)   res1[i, 2] <- tmp[["Sample size"]]   res1[i, 3] <- tmp[["Achieved power"]]   tmp        <- sampleN.RSABE(CV = CV[i], design = design,                               theta0 = theta0, targetpower = target,                               details = FALSE, print = FALSE)   res2[i, 2] <- tmp[["Sample size"]]   res2[i, 3] <- tmp[["Achieved power"]]   # Component of ABEL and RSABE: PE within constraints   res1[i, 4] <- suppressMessages(                   power.scABEL(CV = CV[i], design = design,                                theta0 = theta0, n = res1$n[i], details = TRUE)[3]) res2[i, 4] <- suppressMessages( power.RSABE(CV = CV[i], design = design, theta0 = theta0, n = res2$n[i],                                details = TRUE)[3])   # Component of ABEL and RSABE: ABE   res1[i, 5] <- power.TOST(CV = CV[i], design = design,                            theta0 = theta0, n = res1$n[i]) res2[i, 5] <- power.TOST(CV = CV[i], design = design, theta0 = 0.9, n = res2$n[i])   # unconstrained SABE   res1[i, 6] <- power.scABEL(CV = CV[i], design = design,                              theta0 = theta0, n = res1$n[i], regulator = pure1) res2[i, 6] <- power.RSABE(CV = CV[i], design = design, theta0 = theta0, n = res2$n[i],                              regulator = pure2)   setTxtProgressBar(pb, i / length(CV)) } close(pb) # Plots clr    <- c("#0000AA80", "magenta", "#11AA10", "#CC000080") leg    <- c("PE constraint alone", "ABE", "Unconstrained SABE") dev.new(width = 4.5, height = 4.5) op     <- par(no.readonly = TRUE) par(mar = c(3, 2.8, 0, 0), mgp = c(2, 0.5, 0), cex.axis = 0.9) # ABEL plot(CV, res1$n, type = "n", ylim = range(c(res1[, 3:6], res2[, 3:6])), xlab = expression(italic(CV)[wR]), ylab = "power", las = 1) abline(v = c(0.3, 0.5), lty = 2) grid(); box() lines(CV, res1$overall, lwd = 2, col = clr[1]) lines(CV, res1$PE, lwd = 2, col = clr[2]) lines(CV, res1$ABE, lwd = 2, col = clr[3]) lines(CV, res1$SABE, lwd = 2, col = clr[4]) legend("right", bg = "white", box.lty = 0, seg.len = 3, inset = 0.02, col = clr, legend = c("ABEL", leg), lwd = 2, y.intersp = 1.2, cex = 0.9) # RSABE plot(CV, res2$n, type = "n", ylim = range(c(res1[, 3:6], res2[, 3:6])),      xlab = expression(italic(CV)[wR]), ylab = "power", las = 1) abline(v = 0.3, lty = 2) grid(); box() lines(CV, res2$overall, lwd = 2, col = clr[1]) lines(CV, res2$PE, lwd = 2, col = clr[2]) lines(CV, res2$ABE, lwd = 2, col = clr[3]) lines(CV, res2$SABE, lwd = 2, col = clr[4]) legend("right", bg = "white", box.lty = 0, seg.len = 3, inset = 0.02, col = clr,        legend = c("RSABE", leg), lwd = 2, y.intersp = 1.2, cex = 0.9) par(op) 

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

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