Open LittleBeannie opened 2 years ago
It is an interesting case. Please conduct a simulation for a simplified proportional hazard case for fixed design below.
When randomization ratio is 1, both gsDesign
and npSurvSS
provide similar results.
But when randomization ratio is 2, the event driven
, generalized schoenfeld
and asymptotic
from npSurvSS
provide very different results. This is surprising as I have double checked the implementation of npSurvSS:::npsurvSS:::delta_wlr
that follow exactly the formulas in Section 2.3.3 of Yang & Liu (2019). And the results is also different from gsDesign::nSurv
.
alpha <- 0.025
beta <- 0.2
power <- 1 - beta
surv_scale <- 0.02
loss_scale <- 0.01
hr <- 0.6
random_ratio <- 2 # 1
total_time <- 18
follow_time <- 12
accr_time <- 6
gsDesign::nSurv(
lambdaC = surv_scale,
hr = hr,
eta = loss_scale,
alpha = alpha,
beta = beta,
T = total_time,
minfup = follow_time,
ratio = random_ratio
)
arm0 <- npsurvSS::create_arm(
size = 1, accr_time = accr_time, surv_scale = surv_scale,
loss_scale = loss_scale, follow_time = follow_time
)
arm1 <- npsurvSS::create_arm(
size = random_ratio, accr_time = accr_time, surv_scale = hr * surv_scale,
loss_scale = loss_scale, follow_time = follow_time
)
# Sample size for logrank test
npsurvSS::size_two_arm(arm0, arm1,
power = power, alpha = alpha,
test = list(
test = "weighted logrank", weight = "1",
mean.approx = "event driven"
)
)
npsurvSS::size_two_arm(arm0, arm1,
power = power, alpha = alpha,
test = list(
test = "weighted logrank", weight = "1",
mean.approx = "generalized schoenfeld"
)
)
npsurvSS::size_two_arm(arm0, arm1,
power = power, alpha = alpha,
test = list(
test = "weighted logrank", weight = "1",
mean.approx = "asymptotic"
)
)
> alpha <- 0.025
> beta <- 0.2
> power <- 1 - beta
> surv_scale <- 0.02
> loss_scale <- 0.01
> hr <- 0.6
> random_ratio <- 2 # 1
> total_time <- 18
> follow_time <- 12
> accr_time <- 6
>
> gsDesign::nSurv(
+ lambdaC = surv_scale,
+ hr = hr,
+ eta = loss_scale,
+ alpha = alpha,
+ beta = beta,
+ T = total_time,
+ minfup = follow_time,
+ ratio = random_ratio
+ )
Fixed design, two-arm trial with time-to-event
outcome (Lachin and Foulkes, 1986).
Solving for: Accrual rate
Hazard ratio H1/H0=0.6/1
Study duration: T=18
Accrual duration: 6
Min. end-of-study follow-up: minfup=12
Expected events (total, H1): 130.6948
Expected sample size (total): 716.7034
Accrual rates:
Stratum 1
0-6 119.4506
Control event rates (H1):
Stratum 1
0-Inf 0.02
Censoring rates:
Stratum 1
0-Inf 0.01
Power: 100*(1-beta)=80%
Type I error (1-sided): 100*alpha=2.5%
Randomization (Exp/Control): ratio= 2
>
> arm0 <- npsurvSS::create_arm(
+ size = 1, accr_time = accr_time, surv_scale = surv_scale,
+ loss_scale = loss_scale, follow_time = follow_time
+ )
>
> arm1 <- npsurvSS::create_arm(
+ size = random_ratio, accr_time = accr_time, surv_scale = hr * surv_scale,
+ loss_scale = loss_scale, follow_time = follow_time
+ )
>
> # Sample size for logrank test
> npsurvSS::size_two_arm(arm0, arm1,
+ power = power, alpha = alpha,
+ test = list(
+ test = "weighted logrank", weight = "1",
+ mean.approx = "event driven"
+ )
+ )
n0 n1 n d0 d1 d
247.42005 494.84011 742.26016 59.63000 75.72517 135.35517
>
> npsurvSS::size_two_arm(arm0, arm1,
+ power = power, alpha = alpha,
+ test = list(
+ test = "weighted logrank", weight = "1",
+ mean.approx = "generalized schoenfeld"
+ )
+ )
n0 n1 n d0 d1 d
252.37099 504.74198 757.11297 60.82321 77.24045 138.06366
>
> npsurvSS::size_two_arm(arm0, arm1,
+ power = power, alpha = alpha,
+ test = list(
+ test = "weighted logrank", weight = "1",
+ mean.approx = "asymptotic"
+ )
+ )
n0 n1 n d0 d1 d
218.36848 436.73696 655.10545 52.62836 66.83367 119.46203
> gsDesign::nSurv(
+ lambdaC = surv_scale,
+ hr = hr,
+ eta = loss_scale,
+ alpha = alpha,
+ beta = beta,
+ T = total_time,
+ minfup = follow_time,
+ ratio = random_ratio
+ )
Fixed design, two-arm trial with time-to-event
outcome (Lachin and Foulkes, 1986).
Solving for: Accrual rate
Hazard ratio H1/H0=0.6/1
Study duration: T=18
Accrual duration: 6
Min. end-of-study follow-up: minfup=12
Expected events (total, H1): 121.6416
Expected sample size (total): 617.4126
Accrual rates:
Stratum 1
0-6 102.9021
Control event rates (H1):
Stratum 1
0-Inf 0.02
Censoring rates:
Stratum 1
0-Inf 0.01
Power: 100*(1-beta)=80%
Type I error (1-sided): 100*alpha=2.5%
Equal randomization: ratio=1
>
> arm0 <- npsurvSS::create_arm(
+ size = 1, accr_time = accr_time, surv_scale = surv_scale,
+ loss_scale = loss_scale, follow_time = follow_time
+ )
>
> arm1 <- npsurvSS::create_arm(
+ size = random_ratio, accr_time = accr_time, surv_scale = hr * surv_scale,
+ loss_scale = loss_scale, follow_time = follow_time
+ )
>
> # Sample size for logrank test
> npsurvSS::size_two_arm(arm0, arm1,
+ power = power, alpha = alpha,
+ test = list(
+ test = "weighted logrank", weight = "1",
+ mean.approx = "event driven"
+ )
+ )
n0 n1 n d0 d1 d
305.34136 305.34136 610.68272 73.58945 46.72626 120.31570
>
> npsurvSS::size_two_arm(arm0, arm1,
+ power = power, alpha = alpha,
+ test = list(
+ test = "weighted logrank", weight = "1",
+ mean.approx = "generalized schoenfeld"
+ )
+ )
n0 n1 n d0 d1 d
305.68353 305.68353 611.36705 73.67191 46.77862 120.45053
>
> npsurvSS::size_two_arm(arm0, arm1,
+ power = power, alpha = alpha,
+ test = list(
+ test = "weighted logrank", weight = "1",
+ mean.approx = "asymptotic"
+ )
+ )
n0 n1 n d0 d1 d
314.56677 314.56677 629.13355 75.81284 48.13802 123.95086
The output for ratio 1:1 is similar to the output from other functions/software. However, in the output for ratio 2:1, the events are much smaller than we had expected, different from the production of other software, and power is very different from simulation. I had expected larger number of events under 2:1 compared to 1:1. Also, AHR does not seem reasonable.
The calculation in the new version need to be verified by simulations.