25
25
# ' with the spending time at each analysis.
26
26
# ' @param lstime Default is NULL in which case lower bound spending time is determined by timing.
27
27
# ' Otherwise, this should be a vector of length k (total number of analyses)
28
- # ' with the spending time at each analysis
29
- # ' @param observed_data a list of observed datasets by analyses.
30
- # ' @param event_tbl A data frame with 2 columns: (1) analysis and (2) event (events observed at each analysis, per piecewise interval)
31
- # '
32
- # ' @return A list with input parameters, enrollment rate, analysis, and bound.
28
+ # ' with the spending time at each analysis.
29
+ # ' @param event_tbl A data frame with two columns: (1) analysis and (2) event,
30
+ # ' which represents the events observed at each analysis per piecewise interval.
31
+ # ' This can be defined via the `pw_observed_event()` function or manually entered.
32
+ # ' For example, consider a scenario with two intervals in the piecewise model:
33
+ # ' the first interval lasts 6 months with a hazard ratio (HR) of 1,
34
+ # ' and the second interval follows with an HR of 0.6.
35
+ # ' The data frame `event_tbl = data.frame(analysis = c(1, 1, 2, 2), event = c(30, 100, 30, 200))`
36
+ # ' indicates that 30 events were observed during the delayed effect period,
37
+ # ' 130 events were observed at the IA, and 230 events were observed at the FA.
38
+ # '
39
+ # ' @return A list with input parameters, enrollment rate, failure rate, analysis, and bound.
33
40
# '
34
41
# ' @export
35
42
# '
59
66
# ' ratio <- 1
60
67
# '
61
68
# ' # ------------------------------------------------- #
62
- # ' # Example A: one-sided design (efficacy only)
63
- # ' # ------------------------------------------------- #
64
- # ' # Original design
65
- # ' upper <- gs_spending_bound
66
- # ' upar <- list(sf = sfLDOF, total_spend = alpha)
67
- # ' x <- gs_design_ahr(
68
- # ' enroll_rate = enroll_rate, fail_rate = fail_rate,
69
- # ' alpha = alpha, beta = beta, ratio = ratio,
70
- # ' info_scale = "h0_info",
71
- # ' info_frac = NULL,
72
- # ' analysis_time = c(20, 36),
73
- # ' upper = gs_spending_bound, upar = upar,
74
- # ' lower = gs_b, lpar = rep(-Inf, 2),
75
- # ' test_upper = TRUE, test_lower = FALSE) |> to_integer()
76
- # '
77
- # ' # Observed dataset at IA and FA
78
- # ' set.seed(123)
79
- # '
80
- # ' observed_data <- simtrial::sim_pw_surv(
81
- # ' n = x$analysis$n[x$analysis$analysis == 2],
82
- # ' stratum = data.frame(stratum = "All", p = 1),
83
- # ' block = c(rep("control", 2), rep("experimental", 2)),
84
- # ' enroll_rate = x$enroll_rate,
85
- # ' fail_rate = (fail_rate |> simtrial::to_sim_pw_surv())$fail_rate,
86
- # ' dropout_rate = (fail_rate |> simtrial::to_sim_pw_surv())$dropout_rate)
87
- # '
88
- # ' observed_data_ia <- observed_data |> simtrial::cut_data_by_date(x$analysis$time[1])
89
- # ' observed_data_fa <- observed_data |> simtrial::cut_data_by_date(x$analysis$time[2])
90
- # '
91
- # ' observed_event_ia <- sum(observed_data_ia$event)
92
- # ' observed_event_fa <- sum(observed_data_fa$event)
93
- # '
94
- # ' planned_event_ia <- x$analysis$event[1]
95
- # ' planned_event_fa <- x$analysis$event[2]
96
- # '
97
- # ' # Example A1 ----
98
- # ' # IA spending = observed events / final planned events
99
- # ' # the remaining alpha will be allocated to FA.
100
- # ' ustime <- c(observed_event_ia / planned_event_fa, 1)
101
- # ' gs_update_ahr(
102
- # ' x = x,
103
- # ' ustime = ustime,
104
- # ' observed_data = list(observed_data_ia, observed_data_fa))
105
- # '
106
- # ' # Example A2 ----
107
- # ' # IA, FA spending = observed events / final planned events
108
- # ' ustime <- c(observed_event_ia, observed_event_fa) / planned_event_fa
109
- # ' gs_update_ahr(
110
- # ' x = x,
111
- # ' ustime = ustime,
112
- # ' observed_data = list(observed_data_ia, observed_data_fa))
113
- # '
114
- # ' # Example A3 ----
115
- # ' # IA spending = min(observed events, planned events) / final planned events
116
- # # the remaining alpha will be allocated to FA.
117
- # ' ustime <- c(min(observed_event_ia, planned_event_ia) / planned_event_fa, 1)
118
- # ' gs_update_ahr(
119
- # ' x = x,
120
- # ' ustime = ustime,
121
- # ' observed_data = list(observed_data_ia, observed_data_fa))
122
- # '
123
- # ' # Example A4 ----
124
- # ' # IA spending = min(observed events, planned events) / final planned events
125
- # ' ustime <- c(min(observed_event_ia, planned_event_ia),
126
- # ' min(observed_event_fa, planned_event_fa)) / planned_event_fa
127
- # ' gs_update_ahr(
128
- # ' x = x,
129
- # ' ustime = ustime,
130
- # ' observed_data = list(observed_data_ia, observed_data_fa))
131
- # '
132
- # ' # alpha is upadted to 0.05
133
- # ' gs_update_ahr(
134
- # ' x = x,
135
- # ' alpha = 0.05,
136
- # ' ustime = ustime,
137
- # ' observed_data = list(observed_data_ia, observed_data_fa))
138
- # '
139
- # ' # ------------------------------------------------- #
140
- # ' # Example B: Two-sided asymmetric design,
69
+ # ' # Two-sided asymmetric design,
141
70
# ' # beta-spending with non-binding lower bound
142
71
# ' # ------------------------------------------------- #
143
72
# ' # Original design
154
83
# ' test_lower = c(TRUE, FALSE),
155
84
# ' binding = FALSE) |> to_integer()
156
85
# '
157
- # ' # Example B1 ----
158
- # ' # IA spending = observed events / final planned events
159
- # ' # the remaining alpha will be allocated to FA.
160
- # ' ustime <- c(observed_event_ia / planned_event_fa, 1)
161
- # ' gs_update_ahr(
162
- # ' x = x,
163
- # ' ustime = ustime,
164
- # ' lstime = ustime,
165
- # ' observed_data = list(observed_data_ia, observed_data_fa))
86
+ # ' planned_event_ia <- x$analysis$event[1]
87
+ # ' planned_event_fa <- x$analysis$event[2]
166
88
# '
167
- # ' # Example B2 ----
168
- # ' # IA, FA spending = observed events / final planned events
169
- # ' ustime <- c(observed_event_ia, observed_event_fa) / planned_event_fa
170
- # ' gs_update_ahr(
171
- # ' x = x,
172
- # ' ustime = ustime,
173
- # ' lstime = ustime,
174
- # ' observed_data = list(observed_data_ia, observed_data_fa))
175
89
# '
176
- # ' # Example B3 ----
177
- # ' ustime <- c(min(observed_event_ia, planned_event_ia) / planned_event_fa, 1)
90
+ # ' # Updated design with 190 events observed at IA,
91
+ # ' # where 50 events observed during the delayed effect.
92
+ # ' # IA spending = observed events / final planned events, the remaining alpha will be allocated to FA.
178
93
# ' gs_update_ahr(
179
94
# ' x = x,
180
- # ' ustime = ustime,
181
- # ' lstime = ustime,
182
- # ' observed_data = list(observed_data_ia, observed_data_fa))
95
+ # ' ustime = c(190 / planned_event_fa, 1),
96
+ # ' lstime = c(190 / planned_event_fa, 1),
97
+ # ' event_tbl = data.frame(analysis = c(1, 1),
98
+ # ' event = c(50, 140)))
183
99
# '
184
- # ' # Example B4 ----
185
- # ' # IA spending = min(observed events, planned events) / final planned events
186
- # ' ustime <- c(min(observed_event_ia, planned_event_ia),
187
- # ' min(observed_event_fa, planned_event_fa)) / planned_event_fa
100
+ # ' # Updated design with 190 events observed at IA, and 300 events observed at FA,
101
+ # ' # where 50 events observed during the delayed effect.
102
+ # ' # IA spending = observed events / final planned events, the remaining alpha will be allocated to FA.
188
103
# ' gs_update_ahr(
189
104
# ' x = x,
190
- # ' ustime = ustime,
191
- # ' lstime = ustime,
192
- # ' observed_data = list(observed_data_ia, observed_data_fa))
193
- # '
194
- # ' # Example B5 ----
195
- # ' # alpha is updated to 0.05 ----
196
- # ' gs_update_ahr(x = x, alpha = 0.05)
105
+ # ' ustime = c(190 / planned_event_fa, 1),
106
+ # ' lstime = c(190 / planned_event_fa, 1),
107
+ # ' event_tbl = data.frame(analysis = c(1, 1, 2, 2),
108
+ # ' event = c(50, 140, 50, 250)))
197
109
# '
198
- # ' # Example B6 ----
199
- # ' # updated boundaries only when IA data is observed
200
- # ' ustime <- c(observed_event_ia / planned_event_fa, 1)
110
+ # ' # Updated design with 190 events observed at IA, and 300 events observed at FA,
111
+ # ' # where 50 events observed during the delayed effect.
112
+ # ' # IA spending = minimal of planned and actual information fraction spending
201
113
# ' gs_update_ahr(
202
114
# ' x = x,
203
- # ' ustime = ustime,
204
- # ' lstime = ustime,
205
- # ' observed_data = list(observed_data_ia, NULL))
206
- # '
207
- # ' # ------------------------------------------------- #
208
- # ' # Example C: Two-sided asymmetric design,
209
- # ' # with calendar spending for efficacy and futility bounds
210
- # ' # beta-spending with non-binding lower bound
211
- # ' # ------------------------------------------------- #
212
- # ' # Original design
213
- # ' x <- gs_design_ahr(
214
- # ' enroll_rate = enroll_rate, fail_rate = fail_rate,
215
- # ' alpha = alpha, beta = beta, ratio = ratio,
216
- # ' info_scale = "h0_info",
217
- # ' info_frac = NULL, analysis_time = c(20, 36),
218
- # ' upper = gs_spending_bound,
219
- # ' upar = list(sf = sfLDOF, total_spend = alpha, timing = c(20, 36) / 36),
220
- # ' test_upper = TRUE,
221
- # ' lower = gs_spending_bound,
222
- # ' lpar = list(sf = sfLDOF, total_spend = beta, timing = c(20, 36) / 36),
223
- # ' test_lower = c(TRUE, FALSE),
224
- # ' binding = FALSE) |> to_integer()
115
+ # ' ustime = c(min(190, planned_event_ia) / planned_event_fa, 1),
116
+ # ' lstime = c(min(190, planned_event_ia) / planned_event_fa, 1),
117
+ # ' event_tbl = data.frame(analysis = c(1, 1, 2, 2),
118
+ # ' event = c(50, 140, 50, 250)))
225
119
# '
226
- # ' # Updated design due to potential change of multiplicity graph
120
+ # ' # Alpha is updated to 0.05 ----
227
121
# ' gs_update_ahr(x = x, alpha = 0.05)
228
- # '
229
- # ' # ------------------------------------------------- #
230
- # ' # Example D: one-sided design without TTE dataset as input
231
- # ' # ------------------------------------------------- #
232
- # ' # Original design
233
- # ' upper <- gs_spending_bound
234
- # ' upar <- list(sf = sfLDOF, total_spend = alpha)
235
- # ' x <- gs_design_ahr(
236
- # ' enroll_rate = enroll_rate, fail_rate = fail_rate,
237
- # ' alpha = alpha, beta = beta, ratio = ratio,
238
- # ' info_scale = "h0_info",
239
- # ' info_frac = NULL,
240
- # ' analysis_time = c(20, 36),
241
- # ' upper = gs_spending_bound, upar = upar,
242
- # ' lower = gs_b, lpar = rep(-Inf, 2),
243
- # ' test_upper = TRUE, test_lower = FALSE) |> to_integer()
244
- # '
245
- # ' # Updated design with 100 events observed at IA,
246
- # ' # where 30 events observed during the delayed effect
247
- # ' gs_update_ahr(
248
- # ' x = x,
249
- # ' ustime = c(100/x$analysis$event[2], 1),
250
- # ' event_tbl = data.frame(analysis = c(1, 1),
251
- # ' event_tbl = c(30, 70)))
252
- # '
253
- # ' # Updated design with 100 events observed at IA, 170 events at FA
254
- # ' # where 30 events observed during the delayed effect at IA,
255
- # ' # and 40 events observed during the delayed effect at FA.
256
- # ' gs_update_ahr(
257
- # ' x = x,
258
- # ' ustime = c(100/x$analysis$event[2], 1),
259
- # ' event_tbl = data.frame(analysis = c(1, 1, 2, 2),
260
- # ' event_tbl = c(30, 70, 40, 130)))
261
122
gs_update_ahr <- function (
262
123
x = NULL ,
263
124
alpha = NULL ,
264
125
ustime = NULL ,
265
126
lstime = NULL ,
266
- observed_data = NULL ,
267
127
event_tbl = NULL ) {
268
128
269
129
# ----------------------------------- #
@@ -314,7 +174,7 @@ gs_update_ahr <- function(
314
174
# ----------------------------------- #
315
175
# If users do not input observed data, nor event_tbl
316
176
# which means they update design with a different value of alpha
317
- if (is.null(observed_data ) && is.null( event_tbl )) {
177
+ if (is.null(event_tbl )) {
318
178
319
179
# Check if ustime and lstime matches the spending time of the original design
320
180
if (! is.null(ustime ) && any(ustime != x $ input $ upar $ timing )) {
@@ -375,7 +235,7 @@ gs_update_ahr <- function(
375
235
blinded_est <- NULL
376
236
observed_event <- NULL
377
237
for (i in 1 : n_analysis ) {
378
- if (is.null( observed_data [[ i ]]) && ! (i %in% event_tbl $ analysis )) {
238
+ if (! (i %in% event_tbl $ analysis )) {
379
239
# if there is no observed data at analysis i,
380
240
# for example, we only observed IA data and FA data is unavailable yet
381
241
blinded_est_new <- data.frame (event = x $ analysis $ event [i ],
@@ -384,38 +244,15 @@ gs_update_ahr <- function(
384
244
info0 = x $ analysis $ info0 [i ])
385
245
event_new <- x $ analysis $ event [i ]
386
246
} else {
387
- # if both observed_data and event_tbl provided, check if the events matches
388
- if (! is.null(observed_data [[i ]]) && i %in% event_tbl $ analysis ) {
389
- event_from_observed_data <- simtrial :: fit_pwexp(srv = survival :: Surv(time = observed_data [[i ]]$ tte ,
390
- event = observed_data [[i ]]$ event ),
391
- intervals = cumsum(x $ fail_rate $ duration ))[, 3 ]
392
- event_from_event_tbl <- event_tbl $ event [event_tbl $ analysis == i , ]
393
- if (event_from_observed_data != event_from_event_tbl ) {
394
- stop(" The events from event_tbl mismatches observed_data." )
395
- }
396
- }
397
-
398
- # if there is observed data at analysis i,
399
- # we calculate the blinded estimation based on the observed_data
400
- if (! is.null(observed_data [[i ]])) {
401
- blinded_est_new <- ahr_blinded(surv = survival :: Surv(time = observed_data [[i ]]$ tte ,
402
- event = observed_data [[i ]]$ event ),
403
- intervals = cumsum(x $ fail_rate $ duration ),
404
- hr = x $ input $ fail_rate $ hr ,
405
- ratio = x $ input $ ratio )
406
- event_new <- sum(observed_data [[i ]]$ event )
407
- # we calculate the blinded estimation based on the event_tbl
408
- } else if (i %in% event_tbl $ analysis ) {
409
- q_e <- x $ input $ ratio / (1 + x $ input $ ratio )
410
- event_i <- event_tbl $ event [event_tbl $ analysis == i ]
411
- hr_i <- x $ fail_rate $ hr
412
- event_new <- sum(event_i )
247
+ q_e <- x $ input $ ratio / (1 + x $ input $ ratio )
248
+ event_i <- event_tbl $ event [event_tbl $ analysis == i ]
249
+ hr_i <- x $ fail_rate $ hr
250
+ event_new <- sum(event_i )
413
251
414
- blinded_est_new <- data.frame (event = sum(event_i ),
415
- theta = - sum(log(hr_i ) * event_i ) / sum(event_i ),
416
- info0 = sum(event_i ) * (1 - q_e ) * q_e )
417
- blinded_est_new $ ahr <- exp(- blinded_est_new $ theta )
418
- }
252
+ blinded_est_new <- data.frame (event = sum(event_i ),
253
+ theta = - sum(log(hr_i ) * event_i ) / sum(event_i ),
254
+ info0 = sum(event_i ) * (1 - q_e ) * q_e )
255
+ blinded_est_new $ ahr <- exp(- blinded_est_new $ theta )
419
256
}
420
257
421
258
blinded_est <- rbind(blinded_est , blinded_est_new )
0 commit comments