Perform graphical testing under group sequential design for one or multiple endpoints. See Maurer & Bretz (2013).
Methods
Method new()
Initialize an object for graphical testing procedure. Group sequential design is also supported.
Usage
GraphicalTesting$new(
alpha,
transition,
alpha_spending,
planned_max_info,
hypotheses = NULL,
silent = FALSE
)Arguments
alphainitial alpha allocated to each of the hypotheses.
transitionmatrix of transition weights. Its diagonals should be all 0s. The row sums should be 1s (for better power) or 0s (if no outbound edge from a node).
alpha_spendingcharacter vector of same length of
alpha. Currently it supports'asP','asOF', and'asUser'.planned_max_infovector of integers. Maximum numbers of events (tte endpoints) or patients (non-tte endpoints) at the final analysis of each hypothesis when planning a trial. The actual numbers could be different, which can be specified elsewhere.
hypothesesvector of characters. Names of hypotheses.
silentTRUEif muting all messages and not generating plots.
Method reset()
reset an object of class GraphicalTesting to original status
so that it can be reused.
Method get_alpha()
return alpha allocated to a hypothesis when calling this function.
Note that a function can be called several time with the graph is
updated dynamically. Thus, returned alpha can be different even for
the same hid.
Method get_testable_hypotheses()
return index of hypotheses with non-zero alphas, thus can be tested at the current stage.
Method has_testable_hypotheses()
determine whether at least one hypothesis is testable.
If return FALSE, the testing procedure is completed.
Method get_trajectory()
return testing results by the time this function is called. Note that graphical test is carried out in a sequential manner. Users may want to review the results anytime. Value returned by this function can possibly vary over time.
Method test_hypotheses()
test hypotheses using p-values (and other information in stats)
base on the current graph. All rows should have the same order
number.
Arguments
statsa data frame. It must contain the following columns:
orderinteger. P-values (among others) of hypotheses that can be tested at the same time (e.g., an interim, or final analysis) should be labeled with the same order number. If a hypothesis is not tested at a stage, simply don't put it in
statswith that order number.hypothesescharacter. Name of hypotheses to be tested. They should be identical to those when calling
GraphicalTesting$new.pnominal p-values.
infoobserved number of events or samples at test. These will be used to compute information fractions in group sequential design.
max_infointegers. Maximum information at test. At interim,
max_infoshould be equal toplanned_max_infowhen callingGraphicalTesting$new. At the final stage of a hypothesis, one can update it with observed numbers.
Method test()
test hypotheses using p-values (and other information in stats)
base on the current graph. Users can call this function multiple times.
P-values of the same order should be passed through stats
together. P-values of multiple orders can be passed together as well.
For example, if users only have p-values at current stage, they can call
this function and update the graph accordingly. In this case, column
order in stats is a constant. They can call this
function again when p-values of next stage is available, where
order is another integer. In simulation, if p-values of all
stages are on hand, users can call this function to
test them all in a single pass. In this case, column order in
stats can have different values.
Arguments
statsa data frame. It must contain the following columns:
orderinteger. P-values (among others) of hypotheses that can be tested at the same time (e.g., an interim, or final analysis) should be labeled with the same order number. If a hypothesis is not tested at a stage, simply don't put it in
statswith that order number. If all p-values instatsare tested at the same stage,ordercan be absent.hypothesescharacter. Name of hypotheses to be tested. They should be identical to those when calling
GraphicalTesting$new.pnominal p-values.
infoobserved number of events or samples at test. These will be used to compute information fractions in group sequential design.
max_infointegers. Maximum information at test. At interim,
max_infoshould be equal toplanned_max_infowhen callingGraphicalTesting$new. At the final stage of a hypothesis, one can update it with observed numbers.alpha_spentaccumulative proportion of allocated alpha to be spent if
alpha_spending = "asUser". Set it toNA_real_otherwise. If no hypothesis uses"asUser"instats, this column could be ignored.
Method get_current_testing_results()
return testing results with details by the time this function
is called. This function can be called by users by multiple
times, thus the returned value varies over time.
This function is called by GraphicalTesting::test,
and returns a data frame consisting of columns
hypothesisname of hypotheses.
obs_p_valueobserved p-values.
max_allocated_alphamaximum allocated alpha for the hypothesis.
decision'reject'or'accept'the hypotheses.stagesstage of a hypothesis.
orderorder number that this hypothesis is tested for the last time. It is different from
stages.typeOfDesignname of alpha spending functions.
Method get_current_decision()
get current decisions for all hypotheses. Returned value could changes over time because it depends on the stages being tested already.
Method print()
generic function for print
Arguments
graphlogic.
TRUEif visualizing the current graph, which can vary over time.trajectorylogic.
TRUEif print the current data frame of trajectory, which can vary over time....other arguments supported in
gMCPLite::hGraph, e.g.,trhwandtrhhto control the size of transition box, andtrdigitsto control the digits displayed for transition weights.
Examples
## Example 1
## dry-run to study the behavior of a graph
## without group sequential design
if(interactive()){
eps <- .01
alpha <- c(.01, .04, 0, 0, 0)
transition <- matrix(c(
0, 0, 0, 0, 1,
0, 0, .75, 0, .25,
0, 1/2-eps/2, 0, eps, 1/2-eps/2,
0, 0, 0, 0, 0,
0, 1/2, 1/2, 0, 0
), nrow = 5, byrow = TRUE)
## dummy can be anything, we don't actually use it
asf <- rep('asOF', 5)
## dummy can be anything, we don't actually use it
max_info <- c(300, 1100, 1100, 1100, 500)
hs <- c('H1: UPCR IgA', 'H2: eGFR GN', 'H3: eGFR GN 10wk', 'H5: 2nd Endpoints', 'H4: eGFR IgA')
## initialize an object
gt <- GraphicalTesting$new(alpha, transition, asf, max_info, hs)
print(gt)
## reject hypotheses based on customized order
## to understand the behavior of a testing strategy
## Any other rejection order is possible
gt$reject_a_hypothesis('H1: UPCR IgA')
print(gt)
gt$reject_a_hypothesis('H2: eGFR GN')
print(gt)
gt$reject_a_hypothesis('H4: eGFR IgA')
print(gt)
gt$reject_a_hypothesis('H3: eGFR GN 10wk')
print(gt)
gt$reset()
}
## Example 2
## Example modified from vignettes in gMCPLite:
## Graphical testing for group sequential design
if(interactive()){
## initial alpha split to each of the hypotheses
alpha <- c(.01, .01, .004, .0, .0005, .0005)
## transition matrix of the initial graph
transition <- matrix(c(
0, 1, 0, 0, 0, 0,
0, 0, .5, .5, 0, 0,
0, 0, 0, 1, 0, 0,
0, 0, 0, 0, .5, .5,
0, 0, 0, 0, 0, 1,
.5, .5, 0, 0, 0, 0
), nrow = 6, byrow = TRUE)
## alpha spending functions per hypothesis
asf <- c('asUser', 'asOF', 'asUser', 'asOF', 'asOF', 'asOF')
## planned maximum number of events per hypothesis
max_info <- c(295, 800, 310, 750, 500, 1100)
## name of hypotheses
hs <- c('H1: OS sub',
'H2: OS all',
'H3: PFS sub',
'H4: PFS all',
'H5: ORR sub',
'H6: ORR all')
gt <- GraphicalTesting$new(alpha, transition, asf, max_info, hs)
## print initial graph
gt
## nominal p-values at each stage
## Note: p-values with same order are calculated with the same locked data
## Note: alpha_spent is only specified for hypotheses using custom alpha
## spending function "asUser"
stats <-
data.frame(
order = c(1:3, 1:3, 1:2, 1:2, 1, 1),
hypotheses = c(rep('H1: OS sub', 3), rep('H2: OS all', 3),
rep('H3: PFS sub', 2), rep('H4: PFS all', 2),
'H5: ORR sub', 'H6: ORR all'),
p = c(.03, .0001, .000001, .2, .15, .1, .2, .001, .3, .2, .00001, .1),
info = c(185, 245, 295, 529, 700, 800, 265, 310, 675, 750, 490, 990),
is_final = c(F, F, T, F, F, T, F, T, F, T, T, T),
max_info = c(rep(295, 3), rep(800, 3), rep(310, 2), rep(750, 2), 490, 990),
alpha_spent = c(c(.1, .4, 1), rep(NA, 3), c(.3, 1), rep(NA, 2), NA, NA)
)
## test the p-values from the first analysis, plot the updated graph
gt$test(stats %>% dplyr::filter(order==1))
## test the p-values from the second analysis, plot the updated graph
gt$test(stats %>% dplyr::filter(order==2))
## test the p-values from the third analysis, plot the updated graph
## because no futher test would be done, displayed results are final
gt$test(stats %>% dplyr::filter(order==3))
## plot the final status of the graph
print(gt, trajectory = FALSE)
## you can get final testing results as follow
gt$get_current_testing_results()
## if you want to see step-by-step details
print(gt$get_trajectory())
## equivalently, you can call gt$test(stats) for only once to get same results.
gt$reset()
gt$test(stats)
## if you only want to get the final testing results
gt$get_current_decision()
}
