Given a planned gsNB (or gsDesign) object and observed statistical
information at one or more analyses, recompute the group sequential
boundaries and return an updated design object together with a
gsDesign::gsBoundSummary()-style table.
Arguments
- design
A
gsNBorgsDesignobject produced bygsNBCalendar()(orgsDesign::gsDesign()).- observed_info
Numeric vector of observed statistical information at each analysis conducted so far. Its length must be between 1 and
design$k. If shorter thandesign$k, information at future analyses is projected from the planned design.- spending_time
Optional numeric vector the same length as
observed_infogiving the spending time (between 0 and 1) for each analysis. WhenNULL, spending time equals the information fraction. If shorter thandesign$k, future spending times are taken from the planned design.
Value
A list with components:
- design
The updated
gsDesignobject with recalculated boundaries.- bounds
A data frame from
gsDesign::gsBoundSummary()showing Z-boundaries, nominal p-values, approximate treatment effects at the boundary, and cumulative crossing probabilities at each analysis.- info
A data frame with one row per analysis containing the information fraction (
IF), spending time (spending_time), upper and lower Z-boundaries, and cumulative upper and lower spending.
Details
The observed information determines the covariance structure of the test
statistics (via the information fraction timing), while spending_time
controls how much of the error-spending budget has been used.
When spending_time is NULL (the default), spending is driven by the
observed information fraction. Supplying an explicit spending_time is
useful when the monitoring charter specifies calendar-driven spending that
differs from the observed information fraction.
Examples
library(gsDesign)
#>
#> Attaching package: ‘gsDesign’
#> The following object is masked from ‘package:gsDesignNB’:
#>
#> toInteger
nb_ss <- sample_size_nbinom(
lambda1 = 0.5, lambda2 = 0.3, dispersion = 0.1, power = 0.9,
accrual_rate = 10, accrual_duration = 20, trial_duration = 24
)
gs <- gsNBCalendar(nb_ss, k = 3, analysis_times = c(12, 18, 24))
# After observing information at the first interim
upd <- update_gsNB(gs, observed_info = gs$n.I[1] * 0.95)
upd$bounds
#> Analysis Value Efficacy Futility
#> IA 1: 32% Z 3.0253 -0.2814
#> N: 15 p (1-sided) 0.0012 0.6108
#> ~delta at bound 1.5860 -0.1475
#> P(Cross) if delta=0 0.0012 0.3892
#> P(Cross) if delta=1 0.1318 0.0143
#> IA 2: 64% Z 2.5838 0.8587
#> N: 28 p (1-sided) 0.0049 0.1953
#> ~delta at bound 0.9615 0.3195
#> P(Cross) if delta=0 0.0057 0.8138
#> P(Cross) if delta=1 0.5475 0.0411
#> Final Z 1.9967 1.9967
#> N: 44 p (1-sided) 0.0229 0.0229
#> ~delta at bound 0.5963 0.5963
#> P(Cross) if delta=0 0.0234 0.9766
#> P(Cross) if delta=1 0.9000 0.1000
upd$info
#> Analysis IF spending_time upper_bound lower_bound cum_upper_spend
#> 1 1 0.3245 0.3245 3.0253 -0.2814 0.001242
#> 2 2 0.6441 0.6441 2.5838 0.8587 0.005668
#> 3 3 1.0000 1.0000 1.9967 1.9967 0.025000
#> cum_lower_spend
#> 1 0.014302
#> 2 0.041108
#> 3 0.100000