Skip to contents

Unstratified design

Binary outcome

x <- gs_design_rd(
  p_c = tibble(stratum = "All", rate = 0.2),
  p_e = tibble(stratum = "All", rate = 0.15),
  info_frac = c(0.5, 0.8, 1),
  rd0 = 0,
  alpha = 0.025,
  beta = 0.1,
  ratio = 1,
  stratum_prev = NULL,
  weight = "unstratified",
  upper = gs_spending_bound,
  lower = gs_b,
  upar = list(sf = gsDesign::sfLDOF, timing = c(0.5, 0.8, 1), total_spend = 0.025, param = NULL),
  lpar = rep(-Inf, 3)
)

xi <- x %>% to_integer()

Note that in the original design, the sample size is 1248.7127037, 1997.9403259, 2497.4254074, and in the integer design, the sample size is updated to 1248, 1996, 2498. For the 2 interim analysis, we floor to the closet multiplier of 2, since the randomization ratio is 1. At the final analysis, we ceiling the sample size from 2497.4254074 to 2498 and also make sure the integer sample size is a multiplier of 2.

Please also note that, since the sample size is rounded, the power of the new design also changes a little bit, that is, from 0.9 to 0.9012402.

tibble(
  Design = rep(c("Original design", "Integer design"), each = 3),
  `Sample size` = c(x$analysis$n, xi$analysis$n),
  Z = c(
    (x$bound %>% filter(bound == "upper"))$z,
    (xi$bound %>% filter(bound == "upper"))$z
  ),
  `Information fraction` = c(x$analysis$info_frac, xi$analysis$info_frac),
  Power = c(
    (x$bound %>% filter(bound == "upper"))$probability,
    (xi$bound %>% filter(bound == "upper"))$probability
  )
) %>%
  group_by(Design) %>%
  gt() %>%
  tab_header(
    title = "Comparison between the original/integer design",
    subtitle = "on binary endpoints (unstratified design)"
  ) %>%
  fmt_number(columns = 2:5, decimals = 4)
Comparison between the original/integer design
on binary endpoints (unstratified design)
Sample size Z Information fraction Power
Original design
1,248.7127 2.9626 0.5000 0.2598
1,997.9403 2.2662 0.8000 0.7501
2,497.4254 2.0278 1.0000 0.9000
Integer design
1,248.0000 2.9626 0.4996 0.2612
1,996.0000 2.2662 0.7990 0.7517
2,498.0000 2.0281 1.0000 0.9012

Survival outcome

x <- gs_design_ahr(
  analysis_time = c(12, 24, 36),
  upper = gs_spending_bound,
  lower = gs_b,
  upar = list(sf = gsDesign::sfLDOF, timing = 1:3 / 3, total_spend = 0.025, param = NULL),
  lpar = rep(-Inf, 3)
)
xi <- x %>% to_integer()

Notice that with the integer design, the (i) number of events, (ii) sample size, (iii) power, (iv) information fraction will be different.

tibble(
  Design = rep(c("Original design", "Integer design"), each = 3),
  Events = c(x$analysis$event, xi$analysis$event),
  `Sample size` = c(x$analysis$n, xi$analysis$n),
  Z = c(
    (x$bound %>% filter(bound == "upper"))$z,
    (xi$bound %>% filter(bound == "upper"))$z
  ),
  `Information fraction` = c(x$analysis$info_frac, xi$analysis$info_frac),
  Power = c(
    (x$bound %>% filter(bound == "upper"))$probability,
    (xi$bound %>% filter(bound == "upper"))$probability
  )
) %>%
  group_by(Design) %>%
  gt() %>%
  tab_header(
    title = "Comparison between the original/integer design",
    subtitle = "on survival endpoints (unstratified design)"
  ) %>%
  fmt_number(columns = 2:5, decimals = 4)
Comparison between the original/integer design
on survival endpoints (unstratified design)
Events Sample size Z Information fraction Power
Original design
91.9812 405.7098 3.7103 0.3091 0.003627376
221.2005 486.8518 2.5122 0.7376 0.481734802
298.6001 486.8518 1.9828 1.0000 0.900000000
Integer design
91.0000 403.2286 3.7103 0.3054 0.003520700
221.0000 488.0000 2.5123 0.7360 0.479580151
299.0000 488.0000 1.9830 1.0000 0.900124757

Stratified design

x <- gs_design_rd(
  p_c = tibble(
    stratum = c("biomarker positive", "biomarker negative"),
    rate = c(0.2, 0.25)
  ),
  p_e = tibble(
    stratum = c("biomarker positive", "biomarker negative"),
    rate = c(0.15, 0.22)
  ),
  info_frac = c(0.7, 1),
  rd0 = 0,
  alpha = 0.025,
  beta = 0.1,
  ratio = 1,
  stratum_prev = tibble(
    stratum = c("biomarker positive", "biomarker negative"),
    prevalence = c(0.4, 0.6)
  ),
  weight = "ss",
  upper = gs_spending_bound,
  lower = gs_b,
  upar = list(sf = gsDesign::sfLDOF, total_spend = 0.025, param = NULL, timing = c(0.7, 1)),
  lpar = rep(-Inf, 2)
)

xi <- x %>% to_integer()

Note that in the original design, the sample size is 3434.1150063, 4905.8785804, and in the integer design, the sample size is updated to 3434, 4906. For the 2 interim analysis, we floor to the closet multiplier of 2, since the randomization ratio is 1. At the final analysis, we ceiling the sample size from 4905.8785804 to 4906 and also make sure the integer sample size is a multiplier of 2.

tibble(
  Design = rep(c("Original design", "Integer design"), each = 2),
  `Sample size` = c(x$analysis$n, xi$analysis$n),
  Z = c(
    (x$bound %>% filter(bound == "upper"))$z,
    (xi$bound %>% filter(bound == "upper"))$z
  ),
  `Information fraction` = c(x$analysis$info_frac, xi$analysis$info_frac),
  Power = c(
    (x$bound %>% filter(bound == "upper"))$probability,
    (xi$bound %>% filter(bound == "upper"))$probability
  )
) %>%
  group_by(Design) %>%
  gt() %>%
  tab_header(
    title = "Comparison between the original/integer design",
    subtitle = "on binary endpoints (unstratified design)"
  ) %>%
  fmt_number(columns = 2:5, decimals = 4)
Comparison between the original/integer design
on binary endpoints (unstratified design)
Sample size Z Information fraction Power
Original design
3,434.1150 2.4380 0.7000 0.6161
4,905.8786 1.9999 1.0000 0.9000
Integer design
3,434.0000 2.4380 0.7000 0.6173
4,906.0000 1.9999 1.0000 0.9007