library(gsDesign2)
Tabulating Group Sequential Designs for Clinical Trials: Lucid, Structured, and Compact Summaries
Background
When it comes to clinical trials involving time-to-event endpoints, designing studies to determine the necessary sample size for a desired power is a common practice. Group sequential designs are frequently employed as a tool for such designs. Reporting the intricate details of the design into a concise yet informative table can present significant challenges.
In this post, we present a tool that efficiently consolidates and organizes extensive design information into a single, concise, and coherent table. These summarization functions are readily accessible within the R package gsDesign2
.
gsDesign2
allows users to output summary tables in different format:
as_gt()
: for gt tables;as_rtf()
: for rtf tables.
Build a design
We provide a basic example with simplified design parameters. Since the focus of this documentation is the presentation of the summary table, we skip the detailed introduction of the procedure to build the design (the `design` object below). If readers are interested, please refer to https://cran.r-project.org/package=gsDesign2.
# build the group sequential design
<- gs_design_ahr(
design # time of interim and final analyses
analysis_time = c(12, 24),
# spending bound for efficacy
upper = gs_spending_bound,
# O’Brien-Fleming spending function; total_spend is normally alpha
upar = list(sf = gsDesign::sfLDOF, total_spend = 0.025),
# fixed Z-values will be provided for futility bound
lower = gs_b,
lpar = c(qnorm(0.1), -Inf, -Inf)
)
The design provided above is a comprehensive list
that contains extensive information.
typeof(design)
[1] "list"
The list above comprises input parameters (accessible via design$input
) and four tables (explained below). The task at hand is to merge these four tables into a comprehensive summary table that is both easily understandable and well-organized.
Table 1: Enrollment Summary
This table provides a summary of the enrollment. The total sample size can be obtained by multiplying the duration and rate.
$enroll_rate design
# A tibble: 3 × 3
stratum duration rate
<chr> <dbl> <dbl>
1 All 2 23.4
2 All 2 46.8
3 All 10 70.2
Table 2: Treatment Effect Summary
Same as the input fail_rate
, which captures the treatment effect, including the median of survival, hazard ratio between treatment arms, and other related aspects.
$fail_rate design
# A tibble: 2 × 5
stratum duration fail_rate dropout_rate hr
<chr> <dbl> <dbl> <dbl> <dbl>
1 All 3 0.0770 0.001 0.9
2 All 100 0.0385 0.001 0.6
Table 3: Boundary Summary
A table summarizes the boundaries at each analysis, covering both the efficacy bounds (indicated by rows with bound == upper
) and the futility bounds (indicated by rows with bound == lower
).
$bound design
# A tibble: 3 × 7
analysis bound probability probability0 z `~hr at bound` `nominal p`
<int> <chr> <dbl> <dbl> <dbl> <dbl> <dbl>
1 1 upper 0.0257 0.000509 3.29 0.594 0.000509
2 1 lower 0.00486 0.100 -1.28 1.23 0.9
3 2 upper 0.900 0.0250 1.96 0.818 0.0248
Table 4: Analysis Summary
The table provides a summary of information at each analysis level, including details such as analysis time, sample size, events, and other relevant information. Please note that this table contains one single row for each analysis.
$analysis design
# A tibble: 2 × 9
analysis time n event ahr theta info info0 info_frac
<int> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
1 1 12 702. 159. 0.811 0.210 39.2 39.8 0.419
2 2 24 842. 383. 0.715 0.335 93.5 95.6 1
Summarize a design in gt
To generate a summary table in the gt format with a proper presentation, users can easily accomplish this by utilizing the summary()
function and the as_gt()
function, connected by the pipe operator |>
. This allows for a concise and effective way to obtain a summary table that meets the desired format requirements.
These summarized gt tables include various highlighted features that allow users to customize the default table to fit the specific requirements of their studies.
|>
design summary() |>
as_gt()
Bound summary for AHR design | |||||
AHR approximations of ~HR at bound | |||||
Bound | Z | Nominal p1 | ~HR at bound2 | Cumulative boundary crossing probability | |
---|---|---|---|---|---|
Alternate hypothesis | Null hypothesis | ||||
Analysis: 1 Time: 12 N: 701.7 Event: 159.1 AHR: 0.81 Information fraction: 0.42 | |||||
Futility | -1.28 | 0.9000 | 1.2253 | 0.0049 | 0.1000 |
Efficacy | 3.29 | 0.0005 | 0.5939 | 0.0257 | 0.0005 |
Analysis: 2 Time: 24 N: 842 Event: 382.6 AHR: 0.72 Information fraction: 1 | |||||
Efficacy | 1.96 | 0.0248 | 0.8181 | 0.9000 | 0.0250 |
1 One-sided p-value for experimental vs control treatment. Value < 0.5 favors experimental, > 0.5 favors control. | |||||
2 Approximate hazard ratio to cross bound. |
Feature 1: Custom title, subtitle and spanner
The summary table is designed to display a default title, subtitle, and spanner. However, users are welcome to customize these texts to ensure that the table fits their specific study requirements.
|>
design summary() |>
as_gt(title = "Summary of Group Sequential Design Bounds",
subtitle = "Showing Custom Title, Subtitle and Spanner",
colname_spanner = "Cumulative probability to cross boundary")
Summary of Group Sequential Design Bounds | |||||
Showing Custom Title, Subtitle and Spanner | |||||
Bound | Z | Nominal p1 | ~HR at bound2 | Cumulative probability to cross boundary | |
---|---|---|---|---|---|
Alternate hypothesis | Null hypothesis | ||||
Analysis: 1 Time: 12 N: 701.7 Event: 159.1 AHR: 0.81 Information fraction: 0.42 | |||||
Futility | -1.28 | 0.9000 | 1.2253 | 0.0049 | 0.1000 |
Efficacy | 3.29 | 0.0005 | 0.5939 | 0.0257 | 0.0005 |
Analysis: 2 Time: 24 N: 842 Event: 382.6 AHR: 0.72 Information fraction: 1 | |||||
Efficacy | 1.96 | 0.0248 | 0.8181 | 0.9000 | 0.0250 |
1 One-sided p-value for experimental vs control treatment. Value < 0.5 favors experimental, > 0.5 favors control. | |||||
2 Approximate hazard ratio to cross bound. |
Feature 2: Custom display digits and select variables
The summary table is set to display two decimals by default. Nevertheless, users have the flexibility to output a greater number of decimals to ensure numerical accuracy, if desired.
|>
design summary(
analysis_vars = c("time", "event", "info_frac"),
analysis_decimals = c(0, 0, 2)
|>
) as_gt(title = "Summary of Group Sequential Design Bounds",
subtitle = "Demonstration of Number of Digits to Display")
Summary of Group Sequential Design Bounds | |||||
Demonstration of Number of Digits to Display | |||||
Bound | Z | Nominal p1 | ~HR at bound2 | Cumulative boundary crossing probability | |
---|---|---|---|---|---|
Alternate hypothesis | Null hypothesis | ||||
Analysis: 1 Time: 12 Event: 159 Information fraction: 0.42 | |||||
Futility | -1.28 | 0.9000 | 1.2253 | 0.0049 | 0.1000 |
Efficacy | 3.29 | 0.0005 | 0.5939 | 0.0257 | 0.0005 |
Analysis: 2 Time: 24 Event: 383 Information fraction: 1 | |||||
Efficacy | 1.96 | 0.0248 | 0.8181 | 0.9000 | 0.0250 |
1 One-sided p-value for experimental vs control treatment. Value < 0.5 favors experimental, > 0.5 favors control. | |||||
2 Approximate hazard ratio to cross bound. |
Feature 3: Custom columns to be displayed
The summary table currently displays all possible columns from the bound. However, users have the freedom to select specific columns they wish to include in order to create a more concise and streamlined summary table.
|>
design summary() |>
as_gt(display_columns = c("Analysis", "Bound", "Z", "Probability"),
title = "Summary of Group Sequential Design Bounds",
subtitle = "Showing Only Selected Columns")
Summary of Group Sequential Design Bounds | |||
Showing Only Selected Columns | |||
Bound | Z | Cumulative boundary crossing probability | |
---|---|---|---|
Alternate hypothesis | Null hypothesis | ||
Analysis: 1 Time: 12 N: 701.7 Event: 159.1 AHR: 0.81 Information fraction: 0.42 | |||
Futility | -1.28 | 0.0049 | 0.1000 |
Efficacy | 3.29 | 0.0257 | 0.0005 |
Analysis: 2 Time: 24 N: 842 Event: 382.6 AHR: 0.72 Information fraction: 1 | |||
Efficacy | 1.96 | 0.9000 | 0.0250 |
Feature 4: Custom footnotes
The table is designed to incorporate relevant footnotes by default. These footnotes are specifically included to assist users in understanding the statistical concepts underlying each reported column. This aids users in making statistical inferences to determine whether the hypothesis should be rejected or not.
Rather than default, users also have the flexibility to customize the footnotes in the summary table using a syntax similar to gt::tab_footnote()
. This allows for further customization and refinement of the table’s footnotes to meet specific requirements.
|>
design summary() |>
as_gt(
footnote = list(
content = "Non-binding futility test at IA.",
location = "Bound",
attr = "colname"
),title = "Summary of Group Sequential Design Bounds",
subtitle = "Demonstration of Footnotes"
)
Summary of Group Sequential Design Bounds | |||||
Demonstration of Footnotes | |||||
Bound1 | Z | Nominal p | ~HR at bound | Cumulative boundary crossing probability | |
---|---|---|---|---|---|
Alternate hypothesis | Null hypothesis | ||||
Analysis: 1 Time: 12 N: 701.7 Event: 159.1 AHR: 0.81 Information fraction: 0.42 | |||||
Futility | -1.28 | 0.9000 | 1.2253 | 0.0049 | 0.1000 |
Efficacy | 3.29 | 0.0005 | 0.5939 | 0.0257 | 0.0005 |
Analysis: 2 Time: 24 N: 842 Event: 382.6 AHR: 0.72 Information fraction: 1 | |||||
Efficacy | 1.96 | 0.0248 | 0.8181 | 0.9000 | 0.0250 |
1 Non-binding futility test at IA. |
Output a design in rtf
In addition to save in the format of gt, users can also output the summary tables in rtf by using as_rtf().
|>
design summary() |>
as_rtf(file = "./design.rtf")