library(dplyr)
library(gsDesign)
# Example 1 ----
# Single analysis
# Lachin book p 71 difference of proportions example
pc <- .28 # Control response rate
pe <- .40 # Experimental response rate
p0 <- (pc + pe) / 2 # Ave response rate under H0
# Information per increment of 1 in sample size
info0 <- 1 / (p0 * (1 - p0) * 4)
info <- 1 / (pc * (1 - pc) * 2 + pe * (1 - pe) * 2)
# Result should round up to next even number = 652
# Divide information needed under H1 by information per patient added
gs_design_npe(theta = pe - pc, info = info, info0 = info0)
# Example 2 ----
# Fixed bound
x <- gs_design_npe(
alpha = 0.0125,
theta = c(.1, .2, .3),
info = (1:3) * 80,
info0 = (1:3) * 80,
upper = gs_b,
upar = gsDesign::gsDesign(k = 3, sfu = gsDesign::sfLDOF, alpha = 0.0125)$upper$bound,
lower = gs_b,
lpar = c(-1, 0, 0)
)
x
# Same upper bound; this represents non-binding Type I error and will total 0.025
gs_power_npe(
theta = rep(0, 3),
info = (x %>% filter(bound == "upper"))$info,
upper = gs_b,
upar = (x %>% filter(bound == "upper"))$z,
lower = gs_b,
lpar = rep(-Inf, 3)
)
# Example 3 ----
# Spending bound examples
# Design with futility only at analysis 1; efficacy only at analyses 2, 3
# Spending bound for efficacy; fixed bound for futility
# NOTE: test_upper and test_lower DO NOT WORK with gs_b; must explicitly make bounds infinite
# test_upper and test_lower DO WORK with gs_spending_bound
gs_design_npe(
theta = c(.1, .2, .3),
info = (1:3) * 40,
info0 = (1:3) * 40,
upper = gs_spending_bound,
upar = list(sf = gsDesign::sfLDOF, total_spend = 0.025, param = NULL, timing = NULL),
lower = gs_b,
lpar = c(-1, -Inf, -Inf),
test_upper = c(FALSE, TRUE, TRUE)
)
# one can try `info_scale = "h1_info"` or `info_scale = "h0_info"` here
gs_design_npe(
theta = c(.1, .2, .3),
info = (1:3) * 40,
info0 = (1:3) * 30,
info_scale = "h1_info",
upper = gs_spending_bound,
upar = list(sf = gsDesign::sfLDOF, total_spend = 0.025, param = NULL, timing = NULL),
lower = gs_b,
lpar = c(-1, -Inf, -Inf),
test_upper = c(FALSE, TRUE, TRUE)
)
# Example 4 ----
# Spending function bounds
# 2-sided asymmetric bounds
# Lower spending based on non-zero effect
gs_design_npe(
theta = c(.1, .2, .3),
info = (1:3) * 40,
info0 = (1:3) * 30,
upper = gs_spending_bound,
upar = list(sf = gsDesign::sfLDOF, total_spend = 0.025, param = NULL, timing = NULL),
lower = gs_spending_bound,
lpar = list(sf = gsDesign::sfHSD, total_spend = 0.1, param = -1, timing = NULL)
)
# Example 5 ----
# Two-sided symmetric spend, O'Brien-Fleming spending
# Typically, 2-sided bounds are binding
xx <- gs_design_npe(
theta = c(.1, .2, .3),
info = (1:3) * 40,
binding = TRUE,
upper = gs_spending_bound,
upar = list(sf = gsDesign::sfLDOF, total_spend = 0.025, param = NULL, timing = NULL),
lower = gs_spending_bound,
lpar = list(sf = gsDesign::sfLDOF, total_spend = 0.025, param = NULL, timing = NULL)
)
xx
# Re-use these bounds under alternate hypothesis
# Always use binding = TRUE for power calculations
gs_power_npe(
theta = c(.1, .2, .3),
info = (1:3) * 40,
binding = TRUE,
upper = gs_b,
lower = gs_b,
upar = (xx %>% filter(bound == "upper"))$z,
lpar = -(xx %>% filter(bound == "upper"))$z
)
Run the code above in your browser using DataLab