Package {gst}


Title: Global Statistical Tests for Multiple Endpoints
Version: 0.4.0
Description: Design and evaluate global statistical tests (GST) that combine several endpoints into one test, including O'Brien's ordinary and generalized least squares tests (O'Brien (1984) <doi:10.2307/2531158>), power and sample size calculations, and an O'Brien-based truncated closed testing procedure (Luo et al. (2025) <doi:10.1002/pst.70010>). Two 'shiny' applications support interactive power calculation and the creation of forest plots for multiple endpoints from summary statistics.
License: Apache License (== 2.0)
URL: https://xni7.github.io/gst/, https://github.com/xni7/gst
BugReports: https://github.com/xni7/gst/issues
Encoding: UTF-8
RoxygenNote: 7.3.3
Depends: R (≥ 4.1.0)
Imports: dplyr, forestploter, magrittr, MASS, multcomp, stats, parallel, readr, rhandsontable, shiny, shinyWidgets, htmltools, tidyr, plotly, grDevices, grid, pwr, DT, purrr, tibble, bslib, bsicons, datapasta, sortable, stringr, rclipboard, ggplot2, mvtnorm, reactable, rlang
Suggests: knitr, rmarkdown, gt, testthat (≥ 3.0.0)
VignetteBuilder: knitr
Config/testthat/edition: 3
NeedsCompilation: no
Packaged: 2026-10-24 02:19:01 UTC; venus
Author: Lerong Li [aut, led], Anthony Pileggi [aut], Xiaolong Luo [aut], Xiao Ni [aut, cre], Sarepta Therapeutics Inc. [cph, fnd], Stephen Knapp ORCID iD [ctb], Preston Burns [ctb]
Maintainer: Xiao Ni <mooncase@gmail.com>
Repository: CRAN
Date/Publication: 2026-11-07 17:50:26 UTC

Pipe operator

Description

See magrittr::%>% for details.

Usage

lhs %>% rhs

Arguments

lhs

A value or the magrittr placeholder.

rhs

A function call using the magrittr semantics.

Value

The result of calling rhs(lhs).


Create a compound-symmetric correlation matrix

Description

Create a compound-symmetric correlation matrix

Usage

cor_cs(r, m = 2)

Arguments

r

rho, correlation coefficient (numeric/scalar)

m

number of rows/columns (numeric/scalar)

Value

An m x m numeric matrix with 1 on the diagonal and r elsewhere.

Examples

cor_cs(0.5, m = 3)

Forestplot Example Data

Description

Forestplot Example Data

Usage

forest_data()

Value

A data.frame that can be passed to forest_plot

Examples

head(forest_data())

Draw forest plot

Description

Draw forest plot

Usage

forest_plot(
  dt,
  indent_subgroups = TRUE,
  indent_keyword = "Overall",
  standardize_plot = FALSE,
  flip_arrows = FALSE,
  font_size = NULL,
  footnote_size = NULL,
  plot_pch = 16,
  plot_point_size = NULL,
  plot_zoom = 80,
  plot_x_ticks = NULL,
  plot_symmetric = TRUE,
  ci_t_height = 0.2,
  ci_color = "#000000",
  ci_color_inverted = "#4226bd",
  row_height = NULL,
  color_by_endpoint = FALSE,
  significance_level = 0.05,
  display_cols = NULL,
  display_widths = NULL,
  forest_label = NULL,
  digits = 2,
  arrow_prefix = "Favors",
  arrow_label_left = NULL,
  arrow_label_right = NULL,
  ...
)

Arguments

dt

input data (columns: Endpoint, Group, Comparator, Control, LSMean, low, hi, p, invert)

indent_subgroups

indent subgroup labels (logical/scalar; default = TRUE)

indent_keyword

indent keyword (is this useful)

standardize_plot

normalize/standardize point estimate and CI plot display (logical/scalar)

flip_arrows

flip directional arrows below forestplot (logical/scalar)

font_size

font size (numeric/scalar)

footnote_size

footnote font size (numeric/scalar)

plot_pch

plotting character (numeric/scalar)

plot_point_size

size of plotted point estimate (numeric/scalar)

plot_zoom

zoom level for forestplot (numeric/scalar, range: 0 - 100)

plot_x_ticks

vector of x-axis tick marks for forestplot (numeric/vector)

plot_symmetric

should the forestplot have a symmetric x-axis? (logical/scalar)

ci_t_height

size of confidence interval T endpoint (numeric/scalar; range: 0 - 1)

ci_color

color used for normal forestplot confidence intervals (character/scalar; hex color code)

ci_color_inverted

color used for inverted forestplot confidence intervals (character/scalar; hex color code)

row_height

row height (numeric/scalar)

color_by_endpoint

add coloring for each endpoint (logical/scalar)

significance_level

significance level (alpha) for two-sided confidence interval

display_cols

names of columns to display, in order (character/vector; use NULL for defaults)

display_widths

column widths for the display_cols (numeric/vector; use NULL for defaults)

forest_label

label for forest plot column (character/scalar; use NULL for defaults)

digits

number of digits to round estimate + CI column to (scalar/integer; default = 2; use NULL for no rounding)

arrow_prefix

prefix to use for favor arrows (character/scalar; default = "Favors")

arrow_label_left

label for the left-facing arrow (character/scalar; default = NULL (header for control column))

arrow_label_right

label for the left-facing arrow (character/scalar; default = NULL (header for comparator column))

...

additional arguments passed on to forest_theme

Value

A gtable object

Input Data Requirements

The format of the input data dt is rigid and must include all columns in order, even when specifying the display_cols and only using a subset. See forest_data for example input data with the required columns in the correct order.

Customizing columns

Columns can be customized using the display_cols argument, a character vector with column names in the desired display order. In additional to columns in the input data (dt), two special column names are:

Note that when including additional columns, they should be placed after the required columns in the input data (dt).

By default, if display_cols is non-NULL then all column widths will be set to equal. Use display_widths to further customize column widths; it should be a numeric vector with length equal to display_cols.

Examples

# draw forestplot
forest_data() |> forest_plot()

# standardize forest CIs
forest_data() |>
  forest_plot(
    standardize_plot = TRUE
  )

# custom x-ticks
forest_data() |>
  forest_plot(
    row_height = 1.75,
    plot_x_ticks = c(-1, 0, 1),
    plot_zoom = 100
  )

# custom columns
gst::forest_data() |>
dplyr::mutate(
  newcol1 = "A",
  newcol2 = "B"
) |>
gst::forest_plot(
  display_cols = c("Group", "forest", "est+ci", "p", "newcol1", "newcol2"),
  display_widths = c(0.15, 0.2, 0.15, 0.15, 0.1, 0.1)
)


Create reproducible code for current forestplot

Description

Create reproducible code for current forestplot

Usage

forest_reprex(forestplot, unfold = FALSE)

Arguments

forestplot

output from forest_plot()

unfold

unfold the forest_plot function? (logical/scalar; default = FALSE)

Value

A character vector of R code lines that recreate the plot.

Note

Unfolding the code (unfold = TRUE) will generate a code snippet that uses the forestploter::forest() and related package functions directly; the resulting code does not require the gst package.

WARNING: This function will not create a perfect reprex if you use the ... argument in forest_plot

Examples

fp <- forest_plot(forest_data())
cat(forest_reprex(fp), sep = "\n")

Calculate sample size

Description

Calculate sample size

Usage

get_n(
  power,
  es0,
  es1,
  R,
  alpha = 0.05,
  k,
  method = c("ols", "gls"),
  df_method = c("vd", "vob", "vlt"),
  n0_range = c(2, 1000),
  tolerance = 1e-06
)

Arguments

power

target power

es0

effect size in endpoint 1

es1

effect size in endpoint 2

R

correlation matrix between endpoints

alpha

significance level

k

sample size ratio of treatment vs placebo

method

obrien "ols", "gls"

df_method

degrees-of-freedom method (one of "vd", "vob", "vlt")

n0_range

range of size in placebo to be searched

tolerance

the desired accuracy (convergence tolerance)

Value

A list with the required sample sizes n0 (placebo) and n1 (treatment), each rounded up to a whole number.

Examples

get_n(power = 0.8, es0 = 0.3, es1 = 0.4, R = cor_cs(0.5), k = 1)

Calculate operational effect size

Description

Calculate operational effect size

Usage

get_oes(lambda, R, method = c("ols", "gls"))

Arguments

lambda

vector of effect size for each endpoint

R

correlation matrix of lambda

method

obrien "ols", "gls"

Value

A numeric scalar: the operational (combined) effect size.

Examples

get_oes(lambda = c(0.3, 0.4), R = cor_cs(0.5))

Calculate Power

Description

Calculate Power

Usage

get_power(oes, n0, n1 = n0, df = n0 + n1 - 2, alpha = 0.05)

Arguments

oes

operational effect size

n0

sample size in placebo group

n1

sample size in treatment group

df

degree of freedom

alpha

significance level

Value

A numeric scalar: the two-sided power of the t-test.

Examples

get_power(oes = 0.35, n0 = 50)

Launch the GST Power App

Description

Launch the GST Power App

Usage

gst_power_app(runApp = TRUE)

Arguments

runApp

should the app be run on completion, default is TRUE

Value

With runApp = FALSE, a Shiny app object (class shiny.appobj). With runApp = TRUE (the default), the app is launched and the function returns the value of shiny::runApp() when the app stops.

Examples

app <- gst_power_app(runApp = FALSE)
if (interactive()) {
  gst_power_app()
}

A Shiny app to make a forest plot

Description

A Shiny app to make a forest plot

Usage

make_forestplot_app(runApp = TRUE, plot_width = 1000, plot_height = 500)

Arguments

runApp

should the app be run on completion, default is TRUE

plot_width

Width of the plot in pixels, default is 1200

plot_height

Height of the plot in pixels, default is 800

Value

With runApp = FALSE, a Shiny app object (class shiny.appobj). With runApp = TRUE (the default), the app is launched and the function returns the value of shiny::runApp() when the app stops.

Examples

app <- make_forestplot_app(runApp = FALSE)
if (interactive()) {
  make_forestplot_app()
}

O’Brien test

Description

O’Brien test

Usage

obrien(
  data,
  endpoint_vars,
  treatment_vars,
  method = c("ols", "gls", "ranksum"),
  var.equal = TRUE,
  ...
)

Arguments

data

dataset with treatment and multiple outcomes in wide format

endpoint_vars

the character vectors of outcomes in the dataset dat

treatment_vars

treatment variable in the dataset dat

method

obrien "ols", "gls" and "ranksum" test

var.equal

default TRUE. the obrien paper assumes equal variance and using pooled variance to standardize data

...

other options passed to t.test and wilcox.test

Value

A list with t-statistic, df, pvalue, alternative, and correlation matrix R

Examples


# prepare example data (from multcomp::mtept)
dat <- multcomp::mtept
dat$E4 <- -dat$E4  # align signs for all endpoint

# OLS method
dat |>
   obrien(
     endpoint_vars = c("E1", "E2", "E3", "E4"),
     treatment_vars = "treatment",
     method = "ols"
     )

# GLS one-sided
dat |>
  obrien(
    endpoint_vars = c("E1", "E2", "E3"),
    treatment_vars = "treatment",
    method = "gls",
    alternative = "less"
    )

# Ranksum method
dat |>
  obrien(
    endpoint_vars = c("E1", "E2", "E3", "E4"),
    treatment_vars = "treatment",
    method = "ranksum"
    )


O'Brien Plus: Analytical Power for Joint AND Any Individual Endpoint

Description

This function analytically estimates the statistical power for the scenario where both the O'Brien joint endpoint test is significant AND at least one of the individual endpoints is significant. It also calculates the power for "Joint AND a Specific Individual" (if ind_index is provided). It relies on a multivariate t-distribution approximation of the test statistics.

Usage

obrien_plus(
  n1,
  n2 = n1,
  df = n1 + n2 - 2,
  es_ind,
  cor_mtx,
  ind_index = NULL,
  method = c("ols", "gls"),
  alpha = 0.025,
  one_sided = TRUE
)

Arguments

n1

Numeric, sample size for the first treatment group.

n2

Numeric, sample size for the second treatment group.

df

Numeric, degrees of freedom for the t-distribution approximation (default n1 + n2 - 2).

es_ind

Numeric vector, the standardized mean differences (Cohen's d) for each individual endpoint under the alternative hypothesis.

cor_mtx

Numeric matrix, the correlation matrix (R) among the standardized individual endpoints.

ind_index

Integer, the 1-based index of a specific individual endpoint for which "Joint AND Specific Individual" power is also calculated. Set to NULL if only "Joint AND Any Individual" power is desired.

method

Character, the O'Brien test method to use ("ols" or "gls").

alpha

Numeric, the significance level for each test (e.g., 0.05). Assumes no explicit multiplicity adjustment for the 'AND' or 'OR' conditions.

one_sided

Logical, default TRUE. If TRUE, a one-sided test is assumed. If FALSE, a two-sided test is used, with a warning about power interpretation for positive effect sizes.

Value

a named list containing computation settings and results, including:

Examples

# Generate GST power for 3 endpoints (joint + any)
obrien_plus(
  n1 = 25,
  n2 = 30,
  es_ind = c(1, 0.5, 0.5),
  cor_mtx = cor_cs(0.25, m = 3),
  ind_index = NULL,
  method = "ols",
  alpha = 0.05,
  one_sided = TRUE
  )

# Generate GST power for 4 endpoints (joint + 3rd endpoint)
obrien_plus(
  n1 = 28,
  n2 = 40,
  es_ind = c(1, 0.25, 0.75, 0.5),
  cor_mtx = cor_cs(0.35, m = 4),
  ind_index = 3,
  method = "ols",
  alpha = 0.05,
  one_sided = TRUE
  )


Perform Obrien truncated closed testing

Description

Perform Obrien truncated closed testing

Usage

obt(
  data,
  endpoint_vars,
  jendpoint = NULL,
  treatment_vars,
  alpha = 0.05,
  nu = 0.8,
  method = c("ols", "gls", "ranksum"),
  var.equal = TRUE,
  ...
)

Arguments

data

input data; columns should contain endpoint data and must be named E1, E2

endpoint_vars

vector of endpoint column names (character/vector)

jendpoint

joint endpoint, a vector of individual endpoints (character/vector)

treatment_vars

treatment column name (character/scalar)

alpha

significance level (numeric/scalar)

nu

truncation parameter, between 0 and 1 (numeric/scalar; default = 0.8)

method

estimation method (character/scalar; default = 'OLS')

var.equal

assume equal variances? (logical/scalar; default = TRUE)

...

additional arguments passed to obrien

Value

a list containing the following elements:

Input Data Requirements

The endpoint variables in data must be named E1, E2, E3, etc. for the function to work correctly. If you endpoint columns do not have this naming convention, you must rename them.

Note

This is the truncated closed test as proposed by: Luo, X., Li, L., Savenkov, O., Liu, W., Ni, X., Tang, W. and Guo, W., 2025. Multiple Comparisons Procedures for Analyses of Joint Primary Endpoints and Secondary Endpoints. Pharmaceutical Statistics, 24(3), p.e70010. doi: https://doi.org/10.1002/pst.70010

Examples

dat <- multcomp::mtept
dat$E4 <- -dat$E4  # align signs for all endpoints
obt(
    data = dat,
    endpoint_vars = c("E1","E2","E3","E4"),
    jendpoint = c("E3", "E4"),
    alpha = 0.05,
    nu = 0.6,
    treatment_vars = "treatment",
    method = "ols"
)


Calculate Power by simulation

Description

Calculate Power by simulation

Usage

sim_power(
  n0,
  n1 = n0,
  lambda,
  R,
  alpha = 0.05,
  N = 1000,
  ncore = 1L,
  method = c("ols", "gls"),
  ...,
  verbose = FALSE
)

Arguments

n0

sample size in placebo group

n1

sample size in treatment group

lambda

vector of effect size for each endpoint

R

correlation matrix of lambda

alpha

significance level

N

number of replication

ncore

number of cores for parallel::mclapply() (default 1; values above 1 are not supported on Windows)

method

obrien "ols", "gls"

...

additional arguments passed to obrien

verbose

print progress every 100 replications? (logical/scalar; default = FALSE)

Value

A numeric scalar: the proportion of simulated trials with an O'Brien test p-value at or below alpha.

Examples

sim_power(n0 = 30, lambda = c(0.3, 0.4), R = cor_cs(0.5), N = 20, ncore = 1)