Performs Trial Sequential Analysis (TSA) for meta-analyses of
time-to-event outcomes reported as hazard ratios. Implements the
Schoenfeld required-events sample-size formula generalised for unequal
allocation, the Diversity (D-squared) heterogeneity adjustment of
Wetterslev et al. (2009), and O'Brien-Fleming-type alpha- and
beta-spending trial sequential monitoring boundaries computed at the
inverse-variance information based on observed study-level log-HR
standard errors (not merely event counts), via
a compiled (C++) recursive numerical integration engine ported from
the R package 'RTSA' (Soerensen, Olsen, Lange and Gluud; an R
implementation of the Trial Sequential Analysis software of the Copenhagen
Trial Unit, < https://ctu.dk/tools>), with no fixed software-imposed limit
on the number of looks (subject to available computational resources). Produces a cumulative
Z-curve plot with efficacy, futility, and conventional significance
boundaries. Methodology follows Miladinovic et al. (2013)
Trial Sequential Analysis (TSA) for meta-analyses of hazard ratios, in R.
Adapts the classical Wetterslev/Thorlund/Copenhagen Trial Unit TSA framework to time-to-event outcomes, in the spirit of Miladinovic et al. (2013). It's worth distinguishing what's established methodology versus what this package specifically contributes:
Established components (from the cited literature):
This package's specific implementation choices:
sum(1/SE^2)), used as the accrued-information
measure instead of a simpler event-count approximation,?tsa_hr, src/rtsa_core.h and
inst/REVERSE_ENGINEERING_RTSA.md. The earlier R-only engine
(R/obf_boundaries.R; validated against the published exact
O'Brien-Fleming constant plus Monte Carlo type-I error control) is kept
as a fallback that is ON by default (legacy_fallback = TRUE) and only
runs if the compiled engine fails, clearly flagged in the result whenever
it is used; set legacy_fallback = FALSE for confirmatory or RTSA-parity
work,# install.packages("remotes")
remotes::install_github("tarak-dhaouadi/tsahr")
You'll also need its dependencies if you don't already have them:
install.packages(c("metafor", "readxl", "ggplot2"))
library(tsahr)
# Try it on a bundled example dataset: 20 studies by default;
# tsahr_example_data("HR_meta_2") is the 40-study version
path <- tsahr_example_data()
res <- tsa_hr(
data = path,
target_HR = 0.80, # pre-specified anticipated HR (recommended)
alpha_two_sided = 0.05,
power = 0.80,
allocation_source = "data" # or "manual" with allocation_p = ...
)
summary(res) # full results table
plot(res) # the TSA chart
The subtitle of the chart shows the model/design summary and, on a second
line, the pooled random-effects HR with its 95% CI, the p-value, tau² and I².
With boundary_route = "analysis", the position and size of the
"Analysis-route endpoint ... reached" label can be set with
endpoint_label_x, endpoint_label_y and endpoint_label_size.
By default (re_inference = "standard") the random-effects model uses the
usual normal-theory inference. re_inference = "hksj" (alias "knha")
switches to the Hartung-Knapp-Sidik-Jonkman adjustment, and
re_inference = "Hksj_adhoc" to its ad hoc variant in which the variance
multiplier is never below 1:
res <- tsa_hr(path, target_HR = 0.80, re_inference = "hksj")
plot(res) # the caption names the inference option
The tau² estimator (method), DARIS and the boundaries are unaffected; the
pooled CI/p-value and the cumulative Z-curve (shown as the normal-equivalent
of the HKSJ t statistic) change. The HKSJ statistic is undefined at the
first look (cumulative$Z is NA there, and no point is drawn), and early
looks generally are unstable (very few degrees of freedom) -- tsa_hr()
prints a note about this under verbose = TRUE; see ?tsa_hr.
data can be a data.frame or a path to an .xlsx file with one row per
study and (at least) these columns:
| Column | Meaning |
|---|---|
Study |
Unique study label |
log_HR |
log(hazard ratio) for that study |
Std_Error |
standard error of log_HR |
Events_Treatment |
events in the treatment arm |
N_treatment |
patients randomised to treatment |
Events_controls |
events in the control arm |
N_controls |
patients randomised to control |
Rows should be in chronological (publication) order — TSA results
are order-dependent. Either pre-sort your data yourself, or pass
order_by = "<column name>" (e.g. a publication-year column) to have
tsa_hr() sort it for you explicitly:
res <- tsa_hr(path, target_HR = 0.80, order_by = "Year")
tsa_hr() does not write files itself; use standard R tools:
p <- plot(res)
ggplot2::ggsave("tsa_plot.png", p, width = 11, height = 7.5, dpi = 300)
write.csv(res$cumulative, "tsa_cumulative_results.csv", row.names = FALSE)
write.csv(res$summary_table, "tsa_summary.csv", row.names = FALSE)
target_HR = NA: if you don't specify target_HR,
the required information size is calculated from the observed pooled
effect, which is circular and can make the TSA boundary collapse to
the conventional boundary almost immediately. Set target_HR to a
pre-specified, clinically-anticipated effect for a standard,
publication-quality TSA. See ?tsa_hr for details.method changes more than just the pooled effect estimate: the
heterogeneity-variance (tau^2) estimator selected via method does
not change the mathematical alpha-spending function or the
boundary-calculation algorithm -- those are a fixed part of the
group-sequential design chosen up front (alpha_two_sided, power).
However, because method changes tau^2, it also changes the pooled
SE, the random-effects cumulative Z-curve, D-squared, DARIS, and the
cumulative information schedule -- and therefore which study
corresponds to which information fraction. So while the spending
function itself is unaffected, switching, e.g., method = "DL" to
method = "REML" can still change the boundary values attached to
the observed looks indirectly, by changing the information schedule
those looks land on, and therefore the practical timing of a boundary
crossing.Miladinovic B, Mhaskar R, Hozo I, Kumar A, Mahony H, Djulbegovic B. "Optimal information size in trial sequential analysis of time-to-event outcomes reveals potentially inconclusive results because of the risk of random error." J Clin Epidemiol. 2013;66(6):654-9.
Wetterslev J, Thorlund K, Brok J, Gluud C. "Estimating required information size by quantifying diversity in random-effects model meta-analyses." BMC Med Res Methodol. 2009;9:86.
tsahr contains code ported from the R package
RTSA (Anne Lyngholm Soerensen,
Markus Harboe Olsen, Theis Lange and Christian Gluud), licensed GPL (>= 2):
the C++ boundary engine (src/rtsa_core.h, src/rtsa_engine.cpp), its R
orchestration (R/rtsa_engine.R) and the earlier R-only reconstruction of it
(R/obf_boundaries.R). RTSA is the R version of Trial Sequential Analysis
(TSA), originally developed as a stand-alone Java program by the Copenhagen
Trial Unit; the RTSA manual is heavily inspired by the user manual for TSA by
Kristian Thorlund, Janus Engstrøm, Jørn Wetterslev, Jesper Brok, Georgina
Imberger and Christian Gluud. The original TSA software is available at
https://ctu.dk/tools:
Copenhagen Trial Unit, Centre for Clinical Intervention Research, Department 3344, Rigshospitalet, DK-2100 Copenhagen Ø, Denmark. Tel. +45 3545 7171, Fax +45 3545 7101, E-mail: [email protected]
Because of that, tsahr is licensed GPL (>= 2) (as of 0.2.7.22; earlier
releases were labelled MIT). See inst/COPYRIGHTS for the file-by-file
provenance. If you use tsahr for boundary computations please also cite RTSA
and the TSA software.