Test 1: Examples from spec
Default
The default of gs_power_npe
is a single analysis with type I error controlled.
x1 <- gs_power_npe(theta = 0) %>% filter(Bound == "Upper")
x2 <- gsDesign2:::gs_power_npe_(theta = 0) %>% filter(Bound == "Upper")
Analysis | Bound | Z | Probability | theta | theta1 | IF | info | info0 | info1 | Computated from |
---|---|---|---|---|---|---|---|---|---|---|
1 | Upper | 1.959964 | 0.025 | 0 | 0 | 1 | 1 | 1 | 1 | new version |
1 | Upper | 1.959964 | 0.025 | 0 | 0 | NA | 1 | 1 | 1 | old version |
Fixed bound
x1 <- gs_power_npe(theta = c(.1, .2, .3),
info = (1:3) * 40,
upper = gs_b,
upar = gsDesign::gsDesign(k = 3,sfu = gsDesign::sfLDOF)$upper$bound,
lower = gs_b,
lpar = c(-1, 0, 0)) %>% mutate(`Computated from` = "new version")
x2 <- gs_power_npe_(theta = c(.1, .2, .3),
info = (1:3) * 40,
upper = gs_b,
upar = gsDesign::gsDesign(k = 3,sfu = gsDesign::sfLDOF)$upper$bound,
lower = gs_b,
lpar = c(-1, 0, 0)) %>% mutate(`Computated from` = "old version")
Analysis | Bound | Z | Probability | theta | theta1 | IF | info | info0 | info1 | Computated from |
---|---|---|---|---|---|---|---|---|---|---|
1 | Upper | 3.710303 | 0.001042508 | 0.1 | 0.1 | 0.3333333 | 40 | 40 | 40 | new version |
2 | Upper | 2.511427 | 0.234899008 | 0.2 | 0.2 | 0.6666667 | 80 | 80 | 80 | new version |
3 | Upper | 1.993048 | 0.868689026 | 0.3 | 0.3 | 1.0000000 | 120 | 120 | 120 | new version |
1 | Lower | -1.000000 | 0.051291779 | 0.1 | 0.1 | 0.3333333 | 40 | 40 | 40 | new version |
2 | Lower | 0.000000 | 0.071509147 | 0.2 | 0.2 | 0.6666667 | 80 | 80 | 80 | new version |
3 | Lower | 0.000000 | 0.071522125 | 0.3 | 0.3 | 1.0000000 | 120 | 120 | 120 | new version |
1 | Upper | 3.710303 | 0.001042508 | 0.1 | 0.1 | NA | 40 | 40 | 40 | old version |
2 | Upper | 2.511427 | 0.234899008 | 0.2 | 0.2 | NA | 80 | 80 | 80 | old version |
3 | Upper | 1.993048 | 0.868689026 | 0.3 | 0.3 | NA | 120 | 120 | 120 | old version |
1 | Lower | -1.000000 | 0.051291779 | 0.1 | 0.1 | NA | 40 | 40 | 40 | old version |
2 | Lower | 0.000000 | 0.071509147 | 0.2 | 0.2 | NA | 80 | 80 | 80 | old version |
3 | Lower | 0.000000 | 0.071522125 | 0.3 | 0.3 | NA | 120 | 120 | 120 | old version |
Same fixed efficacy bounds, no futility bound (i.e., non-binding bound), null hypothesis
x1 <- gs_power_npe(theta = rep(0, 3),
info = (1:3) * 40,
upar = gsDesign::gsDesign(k = 3,sfu = gsDesign::sfLDOF)$upper$bound,
lpar = rep(-Inf, 3)) %>% mutate(`Computated from` = "new version")
x2 <- gs_power_npe_(theta = rep(0, 3),
info = (1:3) * 40,
upar = gsDesign::gsDesign(k = 3,sfu = gsDesign::sfLDOF)$upper$bound,
lpar = rep(-Inf, 3)) %>% mutate(`Computated from` = "old version")
Analysis | Bound | Z | Probability | theta | theta1 | IF | info | info0 | info1 | Computated from |
---|---|---|---|---|---|---|---|---|---|---|
1 | Upper | 3.710303 | 0.0001035057 | 0 | 0 | 0.3333333 | 40 | 40 | 40 | new version |
2 | Upper | 2.511427 | 0.0060485045 | 0 | 0 | 0.6666667 | 80 | 80 | 80 | new version |
3 | Upper | 1.993048 | 0.0250002354 | 0 | 0 | 1.0000000 | 120 | 120 | 120 | new version |
1 | Lower | -Inf | 0.0000000000 | 0 | 0 | 0.3333333 | 40 | 40 | 40 | new version |
2 | Lower | -Inf | 0.0000000000 | 0 | 0 | 0.6666667 | 80 | 80 | 80 | new version |
3 | Lower | -Inf | 0.0000000000 | 0 | 0 | 1.0000000 | 120 | 120 | 120 | new version |
1 | Upper | 3.710303 | 0.0001035057 | 0 | 0 | NA | 40 | 40 | 40 | old version |
2 | Upper | 2.511427 | 0.0060485045 | 0 | 0 | NA | 80 | 80 | 80 | old version |
3 | Upper | 1.993048 | 0.0250002354 | 0 | 0 | NA | 120 | 120 | 120 | old version |
1 | Lower | -Inf | 0.0000000000 | 0 | 0 | NA | 40 | 40 | 40 | old version |
2 | Lower | -Inf | 0.0000000000 | 0 | 0 | NA | 80 | 80 | 80 | old version |
3 | Lower | -Inf | 0.0000000000 | 0 | 0 | NA | 120 | 120 | 120 | old version |
Fixed bound with futility only at analysis 1; efficacy only at analyses 2, 3
x1 <- gs_power_npe(theta = c(.1, .2, .3),
info = (1:3) * 40,
upper = gs_b,
upar = c(Inf, 3, 2),
lower = gs_b,
lpar = c(qnorm(.1), -Inf, -Inf)) %>% mutate(`Computated from` = "new version")
x2 <- gs_power_npe_(theta = c(.1, .2, .3),
info = (1:3) * 40,
upper = gs_b,
upar = c(Inf, 3, 2),
lower = gs_b,
lpar = c(qnorm(.1), -Inf, -Inf)) %>% mutate(`Computated from` = "old version")
Analysis | Bound | Z | Probability | theta | theta1 | IF | info | info0 | info1 | Computated from |
---|---|---|---|---|---|---|---|---|---|---|
1 | Upper | Inf | 0.00000000 | 0.1 | 0.1 | 0.3333333 | 40 | 40 | 40 | new version |
2 | Upper | 3.000000 | 0.11291848 | 0.2 | 0.2 | 0.6666667 | 80 | 80 | 80 | new version |
3 | Upper | 2.000000 | 0.88742529 | 0.3 | 0.3 | 1.0000000 | 120 | 120 | 120 | new version |
1 | Lower | -1.281552 | 0.02780962 | 0.1 | 0.1 | 0.3333333 | 40 | 40 | 40 | new version |
2 | Lower | -Inf | 0.02780962 | 0.2 | 0.2 | 0.6666667 | 80 | 80 | 80 | new version |
3 | Lower | -Inf | 0.02780962 | 0.3 | 0.3 | 1.0000000 | 120 | 120 | 120 | new version |
1 | Upper | Inf | 0.00000000 | 0.1 | 0.1 | NA | 40 | 40 | 40 | old version |
2 | Upper | 3.000000 | 0.11291848 | 0.2 | 0.2 | NA | 80 | 80 | 80 | old version |
3 | Upper | 2.000000 | 0.88742529 | 0.3 | 0.3 | NA | 120 | 120 | 120 | old version |
1 | Lower | -1.281552 | 0.02780962 | 0.1 | 0.1 | NA | 40 | 40 | 40 | old version |
2 | Lower | -Inf | 0.02780962 | 0.2 | 0.2 | NA | 80 | 80 | 80 | old version |
3 | Lower | -Inf | 0.02780962 | 0.3 | 0.3 | NA | 120 | 120 | 120 | old version |
Spending function bounds
# Lower spending based on non-zero effect
x1 <- gs_power_npe(theta = c(.1, .2, .3),
info = (1:3) * 40,
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)) %>% mutate(`Computated from` = "new version")
x2 <- gs_power_npe_(theta = c(.1, .2, .3),
info = (1:3) * 40,
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)) %>% mutate(`Computated from` = "old version")
Analysis | Bound | Z | Probability | theta | theta1 | IF | info | info0 | info1 | Computated from |
---|---|---|---|---|---|---|---|---|---|---|
1 | Upper | 3.71030287 | 0.001042508 | 0.1 | 0.1 | 0.3333333 | 40 | 40 | 40 | new version |
2 | Upper | 2.51143381 | 0.234968841 | 0.2 | 0.2 | 0.6666667 | 80 | 80 | 80 | new version |
3 | Upper | 1.99305108 | 0.882718886 | 0.3 | 0.3 | 1.0000000 | 120 | 120 | 120 | new version |
1 | Lower | -1.36250263 | 0.023023722 | 0.1 | 0.1 | 0.3333333 | 40 | 40 | 40 | new version |
2 | Lower | 0.07264138 | 0.055155914 | 0.2 | 0.2 | 0.6666667 | 80 | 80 | 80 | new version |
3 | Lower | 1.85908660 | 0.100000000 | 0.3 | 0.3 | 1.0000000 | 120 | 120 | 120 | new version |
1 | Upper | 3.71030287 | 0.001042508 | 0.1 | 0.1 | NA | 40 | 40 | 40 | old version |
2 | Upper | 2.51143381 | 0.234968841 | 0.2 | 0.2 | NA | 80 | 80 | 80 | old version |
3 | Upper | 1.99305108 | 0.882718886 | 0.3 | 0.3 | NA | 120 | 120 | 120 | old version |
1 | Lower | -1.36250263 | 0.023023722 | 0.1 | 0.1 | NA | 40 | 40 | 40 | old version |
2 | Lower | 0.07264138 | 0.055155914 | 0.2 | 0.2 | NA | 80 | 80 | 80 | old version |
3 | Lower | 1.85908660 | 0.100000000 | 0.3 | 0.3 | NA | 120 | 120 | 120 | old version |
Same bounds, but power under different theta
x1 <- gs_power_npe(theta = c(.15, .25, .35),
info = (1:3) * 40,
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)) %>% mutate(`Computated from` = "new version")
x2 <- gs_power_npe_(theta = c(.15, .25, .35),
info = (1:3) * 40,
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)) %>% mutate(`Computated from` = "old version")
Analysis | Bound | Z | Probability | theta | theta1 | IF | info | info0 | info1 | Computated from |
---|---|---|---|---|---|---|---|---|---|---|
1 | Upper | 3.710303 | 0.002875773 | 0.15 | 0.15 | 0.3333333 | 40 | 40 | 40 | new version |
2 | Upper | 2.511434 | 0.391439113 | 0.25 | 0.25 | 0.6666667 | 80 | 80 | 80 | new version |
3 | Upper | 1.993051 | 0.931364287 | 0.35 | 0.35 | 1.0000000 | 120 | 120 | 120 | new version |
1 | Lower | -1.046275 | 0.023023722 | 0.15 | 0.15 | 0.3333333 | 40 | 40 | 40 | new version |
2 | Lower | 0.519855 | 0.055155914 | 0.25 | 0.25 | 0.6666667 | 80 | 80 | 80 | new version |
3 | Lower | 2.408073 | 0.100000000 | 0.35 | 0.35 | 1.0000000 | 120 | 120 | 120 | new version |
1 | Upper | 3.710303 | 0.002875773 | 0.15 | 0.15 | NA | 40 | 40 | 40 | old version |
2 | Upper | 2.511434 | 0.391439113 | 0.25 | 0.25 | NA | 80 | 80 | 80 | old version |
3 | Upper | 1.993051 | 0.931364287 | 0.35 | 0.35 | NA | 120 | 120 | 120 | old version |
1 | Lower | -1.046275 | 0.023023722 | 0.15 | 0.15 | NA | 40 | 40 | 40 | old version |
2 | Lower | 0.519855 | 0.055155914 | 0.25 | 0.25 | NA | 80 | 80 | 80 | old version |
3 | Lower | 2.408073 | 0.100000000 | 0.35 | 0.35 | NA | 120 | 120 | 120 | old version |
Two-sided symmetric spend, O’Brien-Fleming spending
Typically, 2-sided bounds are binding
x1 <- gs_power_npe(theta = rep(0, 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)) %>% mutate(`Computated from` = "new version")
x2 <- gs_power_npe_(theta = rep(0, 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)) %>% mutate(`Computated from` = "old version")
Analysis | Bound | Z | Probability | theta | theta1 | IF | info | info0 | info1 | Computated from |
---|---|---|---|---|---|---|---|---|---|---|
1 | Upper | 3.710303 | 0.0001035057 | 0 | 0 | 0.3333333 | 40 | 40 | 40 | new version |
2 | Upper | 2.511434 | 0.0060483891 | 0 | 0 | 0.6666667 | 80 | 80 | 80 | new version |
3 | Upper | 1.993051 | 0.0250000000 | 0 | 0 | 1.0000000 | 120 | 120 | 120 | new version |
1 | Lower | -3.710303 | 0.0001035057 | 0 | 0 | 0.3333333 | 40 | 40 | 40 | new version |
2 | Lower | -2.511434 | 0.0060483891 | 0 | 0 | 0.6666667 | 80 | 80 | 80 | new version |
3 | Lower | -1.993051 | 0.0250000000 | 0 | 0 | 1.0000000 | 120 | 120 | 120 | new version |
1 | Upper | 3.710303 | 0.0001035057 | 0 | 0 | NA | 40 | 40 | 40 | old version |
2 | Upper | 2.511434 | 0.0060483891 | 0 | 0 | NA | 80 | 80 | 80 | old version |
3 | Upper | 1.993051 | 0.0250000000 | 0 | 0 | NA | 120 | 120 | 120 | old version |
1 | Lower | -3.710303 | 0.0001035057 | 0 | 0 | NA | 40 | 40 | 40 | old version |
2 | Lower | -2.511434 | 0.0060483891 | 0 | 0 | NA | 80 | 80 | 80 | old version |
3 | Lower | -1.993051 | 0.0250000000 | 0 | 0 | NA | 120 | 120 | 120 | old version |
Re-use these bounds under alternate hypothesis
Always use binding = TRUE for power calculations
xx1 <- gs_power_npe(theta = c(.1, .2, .3),
info = (1:3) * 40,
binding = TRUE,
upar = (x1 %>% filter(Bound == "Upper"))$Z,
lpar = -(x1 %>% filter(Bound == "Upper"))$Z) %>% mutate(`Computated from` = "new version")
xx2 <- gs_power_npe_(theta = c(.1, .2, .3),
info = (1:3) * 40,
binding = TRUE,
upar = (x1 %>% filter(Bound == "Upper"))$Z,
lpar = -(x1 %>% filter(Bound == "Upper"))$Z) %>% mutate(`Computated from` = "old version")
Analysis | Bound | Z | Probability | theta | theta1 | IF | info | info0 | info1 | Computated from |
---|---|---|---|---|---|---|---|---|---|---|
1 | Upper | 3.710303 | 1.042508e-03 | 0.1 | 0.1 | 0.3333333 | 40 | 40 | 40 | new version |
2 | Upper | 2.511434 | 2.349812e-01 | 0.2 | 0.2 | 0.6666667 | 80 | 80 | 80 | new version |
3 | Upper | 1.993051 | 9.020711e-01 | 0.3 | 0.3 | 1.0000000 | 120 | 120 | 120 | new version |
1 | Lower | -3.710303 | 7.035242e-06 | 0.1 | 0.1 | 0.3333333 | 40 | 40 | 40 | new version |
2 | Lower | -2.511434 | 1.510031e-05 | 0.2 | 0.2 | 0.6666667 | 80 | 80 | 80 | new version |
3 | Lower | -1.993051 | 1.512598e-05 | 0.3 | 0.3 | 1.0000000 | 120 | 120 | 120 | new version |
1 | Upper | 3.710303 | 1.042508e-03 | 0.1 | 0.1 | NA | 40 | 40 | 40 | old version |
2 | Upper | 2.511434 | 2.349812e-01 | 0.2 | 0.2 | NA | 80 | 80 | 80 | old version |
3 | Upper | 1.993051 | 9.020711e-01 | 0.3 | 0.3 | NA | 120 | 120 | 120 | old version |
1 | Lower | -3.710303 | 7.035242e-06 | 0.1 | 0.1 | NA | 40 | 40 | 40 | old version |
2 | Lower | -2.511434 | 1.510031e-05 | 0.2 | 0.2 | NA | 80 | 80 | 80 | old version |
3 | Lower | -1.993051 | 1.512598e-05 | 0.3 | 0.3 | NA | 120 | 120 | 120 | old version |
Test 2: Fixed Design
The power at the following analysis is expected at 0.975.
gs_power_npe(theta = 0,
upper = gs_b, upar = qnorm(0.025),
lower = gs_b, lpar = -Inf)
## # A tibble: 2 × 10
## Analysis Bound Z Probability theta theta1 IF info info0 info1
## <int> <chr> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
## 1 1 Upper -1.96 0.975 0 0 1 1 1 1
## 2 1 Lower -Inf 0 0 0 1 1 1 1
Test 3: info
!= info0
!= info1
If one inputs info
in upar
x1_a <- gs_power_npe(theta = c(.1, .2, .3),
info = (1:3) * 80, info0 = (1:3) * 90 + 10, info1 = (1:3) * 70 - 5, info_scale = 0,
upper = gs_b, upar = gsDesign::gsDesign(k = 3, sfu = gsDesign::sfLDOF)$upper$bound,
lower = gs_b, lpar = c(-1, 0, 0)) %>% mutate(`Computated from` = "new version", `Info scale` = 0)
x1_b <- gs_power_npe(theta = c(.1, .2, .3),
info = (1:3) * 80, info0 = (1:3) * 90 + 10, info1 = (1:3) * 70 - 5, info_scale = 1,
upper = gs_b, upar = gsDesign::gsDesign(k = 3, sfu = gsDesign::sfLDOF)$upper$bound,
lower = gs_b, lpar = c(-1, 0, 0)) %>% mutate(`Computated from` = "new version", `Info scale` = 1)
x1_c <- gs_power_npe(theta = c(.1, .2, .3),
info = (1:3) * 80, info0 = (1:3) * 90 + 10, info1 = (1:3) * 70 - 5, info_scale = 2,
upper = gs_b, upar = gsDesign::gsDesign(k = 3, sfu = gsDesign::sfLDOF)$upper$bound,
lower = gs_b, lpar = c(-1, 0, 0)) %>% mutate(`Computated from` = "new version", `Info scale` = 2)
x2 <- gs_power_npe_(theta = c(.1, .2, .3),
info = (1:3) * 80, info0 = (1:3) * 90 + 10, info1 = (1:3) * 70 - 5,
upper = gs_b, upar = gsDesign::gsDesign(k = 3, sfu = gsDesign::sfLDOF)$upper$bound,
lower = gs_b, lpar = c(-1, 0, 0)) %>% mutate(`Computated from` = "old version")
x1_a %>%
union_all(x1_b) %>%
union_all(x1_c) %>%
union_all(x2) %>%
arrange(Analysis) %>%
group_by(Analysis, Bound) %>%
gt() %>%
tab_style(
style = list(cell_fill(color = "#d3edeb")),
locations = cells_body(rows = `Computated from` == "old version"))
Z | Probability | theta | theta1 | IF | info | info0 | info1 | Computated from | Info scale |
---|---|---|---|---|---|---|---|---|---|
1 - Upper | |||||||||
3.710303 | 0.003361090 | 0.1 | 0.1 | 0.3571429 | 100 | 100 | 100 | new version | 0 |
3.710303 | 0.001841687 | 0.1 | 0.1 | 0.3170732 | 65 | 65 | 65 | new version | 1 |
3.710303 | 0.007671740 | 0.1 | 0.1 | 0.3333333 | 80 | 100 | 65 | new version | 2 |
3.710303 | 0.007671740 | 0.1 | 0.1 | NA | 80 | 100 | 65 | old version | NA |
1 - Lower | |||||||||
-1.000000 | 0.022750132 | 0.1 | 0.1 | 0.3571429 | 100 | 100 | 100 | new version | 0 |
-1.000000 | 0.035441540 | 0.1 | 0.1 | 0.3170732 | 65 | 65 | 65 | new version | 1 |
-1.000000 | 0.036819135 | 0.1 | 0.1 | 0.3333333 | 80 | 100 | 65 | new version | 2 |
-1.000000 | 0.036819135 | 0.1 | 0.1 | NA | 80 | 100 | 65 | old version | NA |
2 - Upper | |||||||||
2.511427 | 0.596459227 | 0.2 | 0.2 | 0.6785714 | 190 | 190 | 190 | new version | 0 |
2.511427 | 0.425190347 | 0.2 | 0.2 | 0.6585366 | 135 | 135 | 135 | new version | 1 |
2.511427 | 0.512129734 | 0.2 | 0.2 | 0.6666667 | 160 | 190 | 135 | new version | 2 |
2.511427 | 0.512129734 | 0.2 | 0.2 | NA | 160 | 190 | 135 | old version | NA |
2 - Lower | |||||||||
0.000000 | 0.023865544 | 0.2 | 0.2 | 0.6785714 | 190 | 190 | 190 | new version | 0 |
0.000000 | 0.040277466 | 0.2 | 0.2 | 0.6585366 | 135 | 135 | 135 | new version | 1 |
0.000000 | 0.039313062 | 0.2 | 0.2 | 0.6666667 | 160 | 190 | 135 | new version | 2 |
0.000000 | 0.039313062 | 0.2 | 0.2 | NA | 160 | 190 | 135 | old version | NA |
3 - Upper | |||||||||
1.993048 | 0.975690714 | 0.3 | 0.3 | 1.0000000 | 280 | 280 | 280 | new version | 0 |
1.993048 | 0.954614762 | 0.3 | 0.3 | 1.0000000 | 205 | 205 | 205 | new version | 1 |
1.993048 | 0.971978079 | 0.3 | 0.3 | 1.0000000 | 240 | 280 | 205 | new version | 2 |
1.993048 | 0.971978079 | 0.3 | 0.3 | NA | 240 | 280 | 205 | old version | NA |
3 - Lower | |||||||||
0.000000 | 0.023865545 | 0.3 | 0.3 | 1.0000000 | 280 | 280 | 280 | new version | 0 |
0.000000 | 0.040277546 | 0.3 | 0.3 | 1.0000000 | 205 | 205 | 205 | new version | 1 |
0.000000 | 0.039313070 | 0.3 | 0.3 | 1.0000000 | 240 | 280 | 205 | new version | 2 |
0.000000 | 0.039313070 | 0.3 | 0.3 | NA | 240 | 280 | 205 | old version | NA |
Test 3: Developer Tests
1-sided test
r = 80
x <- gs_power_npe(theta = 0,
info = (1:3) * 400,
binding = FALSE, r = r,
upper = gs_b, #gs_spending_bound,
upar = gsDesign(k = 3, test.type = 1, sfu = sfLDOF)$upper$bound,
#list(par = list(sf = gsDesign::sfLDOF, param = NULL, total_spend = 0.025)),
lower = gs_b,
lpar = rep(-Inf, 3)) %>% filter(Bound == "Upper")
y <- gsDesign2:::gs_power_npe_(theta = 0,
info = (1:3) * 400,
binding = FALSE, r = r,
upper = gs_b, #gs_spending_bound,
upar = gsDesign(k = 3, test.type = 1, sfu = sfLDOF)$upper$bound,
#list(par = list(sf = gsDesign::sfLDOF, param = NULL, total_spend = 0.025)),
lower = gs_b,
lpar = rep(-Inf, 3)) %>% filter(Bound == "Upper")
z <- gsProbability(k = 3,
theta = 0,
n.I = (1:3) * 400,
b = gsDesign(k = 3, test.type = 1, sfu = sfLDOF)$upper$bound, a = rep(-20, 3), r = r)
Calculated from | upper bound | upper prob |
---|---|---|
1 | ||
new version | 3.710303 | 0.0001035057 |
old version | 3.710303 | 0.0001035057 |
gsDesign | 3.710303 | 0.0001035057 |
2 | ||
new version | 2.511427 | 0.0060483973 |
old version | 2.511427 | 0.0060483973 |
gsDesign | 2.511427 | 0.0060483970 |
3 | ||
new version | 1.993048 | 0.0250000020 |
old version | 1.993048 | 0.0250000020 |
gsDesign | 1.993048 | 0.0250000013 |
Test 4: Independent Tests
Expect equal with mvtnorm for efficacy and futility bounds
info <- c(40, 100)
r <- info[1] / info[2]
test<-gs_power_npe(theta = 0,
info = info,
info0 = NULL,
binding = FALSE,
upper = gs_spending_bound,
upar = list(sf = gsDesign::sfLDOF, param = NULL, total_spend = 0.025),
lower = gs_spending_bound,
lpar = list(sf = gsDesign::sfLDOF, param = NULL, total_spend = 0.02)
)
test1 <- test%>% filter(Bound == "Upper")
test2 <- test%>% filter(Bound == "Lower")
alpha.t <- 0.025
b.ia <- gsDesign::sfLDOF(alpha = alpha.t, t = r)
alpha.ia <- b.ia$spend
Pb <- function(alpha.t, alpha.ia, r, b){
temp = mvtnorm::pmvnorm(lower = c(-Inf, b),
upper = c(qnorm(1-alpha.ia), Inf),
corr = rbind(c(1, sqrt(r)), c(sqrt(r), 1)))
return(alpha.t - alpha.ia - temp)
}
b <- uniroot(Pb, c(1.96, 4), alpha.t = alpha.t, alpha.ia = alpha.ia, r = r)
pb <- 1- pnorm(b$root)
expect_equal(object = test1$Z, expected = c(qnorm(1-alpha.ia),b$root), tolerance = 0.001)
expect_equal(object = test1$Probability, expected = cumsum(c(b.ia$spend,pb)), tolerance = 0.001)
beta.t <- 0.02
a.ia <- gsDesign::sfLDOF(alpha = beta.t, t = r)
beta.ia <- a.ia$spend
Pa <- function(beta.t, beta.ia, r, a){
temp <- mvtnorm::pmvnorm(lower = c(-Inf, qnorm(beta.ia)),
upper = c(a, Inf),
corr = rbind(c(1, sqrt(r)), c(sqrt(r), 1)))
return(beta.t - beta.ia - temp)
}
a <- uniroot(Pa, c(-4, 1.96), beta.t = beta.t, beta.ia = beta.ia, r = r)
pa <- pnorm(a$root)
expect_equal(object = test2$Z, expected = c(qnorm(beta.ia), a$root), tolerance = 0.001)
expect_equal(object = test2$Probability, expected = cumsum(c(a.ia$spend,pa)), tolerance = 0.001)
Expect equal with gsDesign::gsProbability
outcome for efficacy bounds
info <- c(40, 150, 200)
x <- gs_power_npe(theta = .1,
info = info, binding = FALSE,
upper = gs_spending_bound,
upar = list(sf = gsDesign::sfLDOF, param = NULL, total_spend = 0.025),
lower = gs_b,
lpar = rep(-Inf, 3)) %>% filter(Bound == "Upper")
y <- gs_power_npe(theta = .1,
info = info, binding = FALSE,
upper = gs_spending_bound,
upar = list(sf = gsDesign::sfLDOF, param = NULL, total_spend = 0.025),
lower = gs_b,
lpar = rep(-Inf, 3)) %>% filter(Bound == "Upper")
z <- gsDesign::gsProbability(k = 3, theta = .1,
n.I = info,
a = rep(-20, 3),
b = gsDesign(k = 3, test.type=1, sfu = sfLDOF, n.I = info)$upper$bound)
Calculated from | upper bound | upper prob |
---|---|---|
1 | ||
new version | 4.876885 | 1.095752e-05 |
old version | 4.876885 | 1.095752e-05 |
gsDesign | 4.876885 | 1.095752e-05 |
2 | ||
new version | 2.339724 | 1.324308e-01 |
old version | 2.339724 | 1.324308e-01 |
gsDesign | 2.339719 | 1.324317e-01 |
3 | ||
new version | 2.011782 | 2.870640e-01 |
old version | 2.011782 | 2.870640e-01 |
gsDesign | 2.011778 | 2.870653e-01 |
Test 5: Compare with gsDesign
under information-based design
Information-based design is useful when testing for a natural parameter \(\delta\) (e.g., treatment difference on a relevant scale such as risk difference) where the variance of the estimate of \(\delta\) is unknown. The basic canonical form of represents information-based design, so it is a particularly simple way to check corresponding basic calculations for sample size, bounds and power in gs_power_npe()
and gs_design_npe()
.
Step 1: set the design assumptions
k <- 2 # Number of analyses
test.type <- 4
alpha <- 0.025 # 1-sided Type I error
beta <- 0.15 # Type 2 error (1 - targeted power)
astar <- .1
timing <- 0.4 # Timing (information fraction) at interim analyses
sfu <- sfHSD # Efficacy bound spending function
sfupar <- -1 # Upper bound spending function parameters, if any
sfl <- sfLDPocock# Lower bound spending function, if used (test.type > 2)
sflpar <- 0 # Lower bound spending function parameters, if any
delta <- 0.1 # Natural parameter difference (assumed value - H0 value)
delta1 <- 0.1 # Natural parameter assumed value
delta0 <- 0 # Natural parameter difference under H0
endpoint <- 'info'
n.fix <- 0