| Type: | Package |
| Title: | Sequential Trial Emulation |
| Version: | 1.4.4 |
| Description: | Implementation of sequential trial emulation for the analysis of observational databases. The 'SEQTaRget' software accommodates time-varying treatments and confounders, as well as binary and failure time outcomes. 'SEQTaRget' allows to compare both static and dynamic strategies, can be used to estimate observational analogs of intention-to-treat and per-protocol effects, and can adjust for potential selection bias induced by losses-to-follow-up. (Paper to come). |
| License: | MIT + file LICENSE |
| Encoding: | UTF-8 |
| LazyData: | true |
| Suggests: | rmarkdown, testthat (≥ 3.0.0) |
| Imports: | data.table, parglm, doFuture, doRNG, fastglm, future, future.apply, ggplot2, knitr, methods, stringr, survival, parallelly, utils |
| Config/roxygen2/markdown: | TRUE |
| Config/roxygen2/version: | 8.1.0 |
| Config/testthat/edition: | 3 |
| Depends: | R (≥ 4.1) |
| URL: | https://causalinference.github.io/SEQTaRget/, https://github.com/CausalInference/SEQTaRget |
| VignetteBuilder: | knitr |
| NeedsCompilation: | no |
| Packaged: | 2026-08-28 06:45:33 UTC; runner |
| Author: | Ryan O'Dea |
| Maintainer: | Ryan O'Dea <ryan.odea@psi.ch> |
| Repository: | CRAN |
| Date/Publication: | 2026-08-28 07:50:02 UTC |
SEQTaRget: Sequential Trial Emulation
Description
Implementation of sequential trial emulation for the analysis of observational databases. The 'SEQTaRget' software accommodates time-varying treatments and confounders, as well as binary and failure time outcomes. 'SEQTaRget' allows to compare both static and dynamic strategies, can be used to estimate observational analogs of intention-to-treat and per-protocol effects, and can adjust for potential selection bias induced by losses-to-follow-up. (Paper to come).
Author(s)
Maintainer: Ryan O'Dea ryan.odea@psi.ch (ORCID)
Authors:
Ryan O'Dea ryan.odea@psi.ch (ORCID)
Tom Palmer remlapmot@hotmail.com (ORCID) (ROR)
Paul Madley-Dowd p.madley-dowd@bristol.ac.uk (ORCID)
Alejandro Szmulewicz aszmulewicz@hsph.harvard.edu (ORCID)
Miguel A. Hernán mhernan@hsph.harvard.edu (ORCID)
Other contributors:
The President and Fellows of Harvard College (ROR) [copyright holder]
See Also
Useful links:
Print a coefficient table from a cleaned fastglm object
Description
Print a coefficient table from a cleaned fastglm object
Usage
.coef_table(model)
Arguments
model |
a fastglm object (may have row-level vectors stripped) |
Function to return the internal data from a SEQuential object
Description
Function to return the internal data from a SEQuential object
Usage
SEQ_data(object)
Arguments
object |
SEQoutput object |
Value
data.table
Simulated observational example data for SEQuential
Description
Simulated observational example data for SEQuential()
Usage
SEQdata
Format
A data frame with 12,180 rows and 11 columns:
- ID
Integer: Unique ID emulating individual patients
- time
Integer: Time of observation, always begins at 0, max time of 59. Should be continuous
- eligible
Binary: eligibility criteria for timepoints
- outcome
Binary: If an outcome is observed at this time point
- tx_init
Binary: If treatment is observed at this time point
- sex
Binary: Sex of the emulated patient
- N
Numeric: Normal random variable from N(10,5)
- L
Numeric: 4% continuously increase from U(0, 1)
- P
Numeric: 2% continuously decrease from U(9, 10)
- excusedOne
Binary: Once one, always one variable emulating an excuse for treatment switch
- excusedZero
Binary: Once one, always one variable emulating an excuse for treatment switch
Simulated lost-to-followup example data for SEQuential()
Description
Simulated lost-to-followup example data for SEQuential()
Usage
SEQdata.LTFU
Format
A dataframe with 54,687 rows and 13 columns:
- ID
Integer: Unique ID emulating individual patients
- time
Integer: Time of observation, always begins at 0, max time of 59; however, if lost-to-followup, time is truncated at a random point
- eligible
Binary: eligibility criteria for timepoints
- outcome
Binary: If an outcome is observed at this time point
- tx_init
Binary: If treatment is observed at this time point
- sex
Binary: Sex of the emulated patient
- N
Numeric: Normal random variable from N(10,5)
- L
Numeric: 4% continuously increase from U(0, 1)
- P
Numeric: 2% continuously decrease from U(9, 10)
- excusedOne
Binary: Once one, always one variable emulating an excuse for treatment switch
- excusedZero
Binary: Once one, always one variable emulating an excuse for treatment switch
- LTFU
Binary: Flag for losing a simulated ID to followup, if 1 there are no more records of the ID afterwards
- eligible_cense
Binary: emulates columns which are eligible to entering into censoring models (e.g. if you want to limit columns for the LTFU model)
Simulated multitreatment example data for SEQuential() multinomial models
Description
Simulated multitreatment example data for SEQuential() multinomial models
Usage
SEQdata.multitreatment
Format
A dataframe with 5,976 rows and 11 columns:
- ID
Integer: Unique ID emulating individual patients
- time
Integer: Time of observation, always begins at 0, max time of 59; however, if lost-to-followup, time is truncated at a random point
- eligible
Binary: eligibility criteria for timepoints
- outcome
Binary: If an outcome is observed at this time point
- tx_init
Integer: Which treatment is observed at this time point
- sex
Binary: Sex of the emulated patient
- N
Numeric: Normal random variable from N(10,5)
- L
Numeric: 4% continuously increase from U(0, 1)
- P
Numeric: 2% continuously decrease from U(9, 10)
- excusedOne
Binary: Once one, always one variable emulating an excuse for treatment switch
- excusedZero
Binary: Once one, always one variable emulating an excuse for treatment switch
Estimate the (very rough) time to run SEQuential analysis on current machine
Description
Estimate the (very rough) time to run SEQuential analysis on current machine
Usage
SEQestimate(
data,
id.col,
time.col,
eligible.col,
treatment.col,
outcome.col,
time_varying.cols = list(),
fixed.cols = list(),
method,
options,
verbose = TRUE
)
Arguments
data |
data.frame or data.table, if not already expanded with |
id.col |
String: column name of the id column |
time.col |
String: column name of the time column |
eligible.col |
String: column name of the eligibility column |
treatment.col |
String: column name of the treatment column |
outcome.col |
String: column name of the outcome column |
time_varying.cols |
List: column names for time varying columns |
fixed.cols |
List: column names for fixed columns |
method |
String: method of analysis to perform |
options |
List: optional list of parameters from |
verbose |
Logical: if |
Details
This is a rough heuristic only. Empirically its predictions land
within roughly a factor of two of observed run time, and the direction of
the error depends on the configuration (e.g. it can over- or under-estimate
as followup.max changes), so the result should be treated as an
order-of-magnitude guide rather than a reliable timing.
Value
A list of (very rough) estimates for the time required for SEQuential containing:
-
modelTimeestimated time used when running models -
expansionTimeestimated time used when expanding data -
totalTimesum of model and expansion time
Creates an expanded dataset for use with SEQuential()
Description
Creates an expanded dataset for use with SEQuential()
Usage
SEQexpand(params)
Arguments
params |
SEQparams object built in the SEQuential function |
Parameter Builder for SEQuential Model and Estimates
Description
Parameter Builder for SEQuential Model and Estimates
Usage
SEQopts(
bootstrap = FALSE,
bootstrap.nboot = 100,
bootstrap.sample = 0.8,
bootstrap.CI = 0.95,
bootstrap.CI_method = "se",
cense = NA,
cense.denominator = NA,
cense.eligible = NA,
cense.numerator = NA,
compevent = NA,
covariates = NA,
data.return = FALSE,
denominator = NA,
deviation = FALSE,
deviation.col = NA,
deviation.conditions = c(NA, NA),
deviation.excused = FALSE,
deviation.excused_cols = c(NA, NA),
end_of_fup = FALSE,
end_of_fup.time = NA,
end_of_fup.type = "binary",
end_of_fup.window = 0,
excused = FALSE,
excused.cols = c(NA, NA),
expand.only = FALSE,
fastglm.method = 2L,
followup.class = FALSE,
followup.include = TRUE,
followup.max = Inf,
followup.min = 0,
followup.spline = FALSE,
followup.spline.df = 4L,
glm.package = "fastglm",
hazard = FALSE,
indicator.baseline = "_bas",
indicator.squared = "_sq",
km.curves = FALSE,
multinomial = FALSE,
ncores = availableCores(omit = 1L),
nthreads = getDTthreads(),
numerator = NA,
parallel = FALSE,
parglm.control = NULL,
plot.colors = c("#F8766D", "#00BFC4", "#555555"),
plot.labels = NA,
plot.subtitle = NA,
plot.title = NA,
plot.type = "survival",
risk.times = NA,
seed = NULL,
selection.first_trial = FALSE,
selection.prob = 0.8,
selection.random = FALSE,
subgroup = NA,
survival.max = Inf,
treat.level = c(0, 1),
trial.include = TRUE,
visit = NA,
visit.denominator = NA,
visit.numerator = NA,
weight.eligible_cols = c(),
weight.lower = 0,
weight.lag_condition = TRUE,
weight.p99 = FALSE,
weight.preexpansion = TRUE,
weight.upper = Inf,
weighted = FALSE
)
Arguments
bootstrap |
Logical: defines if |
bootstrap.nboot |
Integer: number of bootstraps, default is |
bootstrap.sample |
Numeric: percentage of data to use when bootstrapping, should be in [0, 1], default is |
bootstrap.CI |
Numeric: defines the confidence interval after bootstrapping, default is |
bootstrap.CI_method |
Character: selects which way to calculate bootstraps confidence intervals ( |
cense |
String: column name for additional censoring variable, e.g. loss-to-follow-up |
cense.denominator |
String: censoring denominator covariates to the right hand side of a formula object |
cense.eligible |
String: column name for indicator column defining which rows to use for censoring model |
cense.numerator |
String: censoring numerator covariates to the right hand side of a formula object |
compevent |
String: column name for competing event indicator |
covariates |
String: covariates to the right hand side of a formula object |
data.return |
Logical: whether to return the expanded dataframe with weighting information, default is |
denominator |
String or character vector: denominator covariates to the right hand side of a formula object. A single string fits the same model in every treatment arm. A vector with one formula per |
deviation |
Logical: create switch based on deviation from column |
deviation.col |
Character: column name for deviation |
deviation.conditions |
Character list: RHS evaluations of the same length as |
deviation.excused |
Logical: whether deviations should be excused by |
deviation.excused_cols |
Character list: excused columns for deviation switches |
end_of_fup |
Logical: estimate an end-of-follow-up outcome - one measured at a single follow-up time rather than as a time-to-event - instead of fitting a survival outcome model, default is |
end_of_fup.time |
Numeric: the follow-up time |
end_of_fup.type |
String: type of end-of-follow-up outcome, either |
end_of_fup.window |
Numeric: half-width of the window used when a trial-period has no outcome measurement at exactly |
excused |
Logical: in the case of censoring, whether there is an excused condition, default is |
excused.cols |
List: list of column names for treatment switch excuses - should be the same length, and ordered the same as |
expand.only |
Logical: if |
fastglm.method |
Integer: decomposition method for fastglm ( |
followup.class |
Logical: treat followup as a class, e.g. expands every time to it's own indicator column, default is |
followup.include |
Logical: whether or not to include 'followup' and 'followup_squared' in the outcome model, default is |
followup.max |
Numeric: maximum time to expand about, default is |
followup.min |
Numeric: minimum follow-up time since trial enrollment to include, must be non-negative, default is |
followup.spline |
Logical: treat followup as a natural cubic spline ( |
followup.spline.df |
Integer: degrees of freedom passed to |
glm.package |
Character: package to use for fitting GLMs, either |
hazard |
Logical: hazard error calculation instead of survival estimation, default is |
indicator.baseline |
String: identifier for baseline variables in |
indicator.squared |
String: identifier for squared variables in |
km.curves |
Logical: Kaplan-Meier survival curve creation and data return, default is |
multinomial |
Logical: whether to expect multilevel treatment values, default is |
ncores |
Integer: number of cores to use in parallel processing, default is one less than system max, see |
nthreads |
Integer: number of threads to use for data.table processing, default is |
numerator |
String or character vector: numerator covariates to the right hand side of a formula object. A single string fits the same model in every treatment arm. A vector with one formula per |
parallel |
Logical: define if the SEQuential process is run in parallel, default is |
parglm.control |
A control object from |
plot.colors |
Character: Colors for output plot if |
plot.labels |
Character: Color labels for output plot if |
plot.subtitle |
Character: Subtitle for output plot if |
plot.title |
Character: Title for output plot if |
plot.type |
Character: Type of plot to create if |
risk.times |
Numeric vector: follow-up times (in the data's follow-up units) at which to report risk difference and risk ratio when |
seed |
Integer: starting seed; the default |
selection.first_trial |
Logical: selects only the first eligible trial in the expanded dataset, default |
selection.prob |
Numeric: percent of total IDs to select for |
selection.random |
Logical: randomly selects IDs with replacement to run analysis, default |
subgroup |
Character: Column name to stratify outcome models on |
survival.max |
Numeric: maximum time for survival curves, default is |
treat.level |
List: treatment levels to compare, default is |
trial.include |
Logical: whether or not to include 'trial' and 'trial_squared' in the outcome model, default is |
visit |
String: column name for visit indicator variable, e.g. |
visit.denominator |
String: visit denominator covariates to the right hand side of a formula object |
visit.numerator |
String: visit numerator covariates to the right hand side of a formula object |
weight.eligible_cols |
List: list of column names for indicator columns defining which weights are eligible for weight models - in order of |
weight.lower |
Numeric: IPCW weights truncated at this lower bound, must be non-negative, default is |
weight.lag_condition |
Logical: whether weights should be conditioned on treatment lag value, default |
weight.p99 |
Logical: forces weight truncation at 1st and 99th percentile weights, will override provided |
weight.preexpansion |
Logical: whether weighting should be done on pre-expanded data, default |
weight.upper |
Numeric: weights truncated at upper end at this weight, default is |
weighted |
Logical: whether or not to perform weighted analysis, default is |
Value
An object of class 'SEQopts'
An S4 class of user options to feed into the SEQuential processes and estimates
This class should match SEQopts in file SEQopts.R
Description
An S4 class of user options to feed into the SEQuential processes and estimates
This class should match SEQopts in file SEQopts.R
An S4 class used to hold the outputs for the SEQuential process
Description
An S4 class used to hold the outputs for the SEQuential process
Slots
paramsSEQparams object
outcomeoutcome covariates
numeratornumerator covariates
denominatordenominator covariates
outcome.modellist of length
bootstrap.nbootcontaining outcome coefficientshazardhazard ratio
survival.curveggplot object for the survival curves
survival.datadata.table of survival data
risk.differencerisk difference calculated from survival data
risk.ratiorisk ratio calculated from survival data
timetime used for the SEQuential process
eof.dataend-of-follow-up estimates per treatment arm when
end_of_fup = TRUE, empty otherwise. Seeend_of_fup()eof.comparisonpairwise between-arm contrasts of the end-of-follow-up estimates when
end_of_fup = TRUE, empty otherwiseweight.statisticsinformation from the weighting process, containing weight coefficients and weight statistics
infolist of diagnostic tables (outcome, follow-up, switch, and competing-event counts where applicable), each split by baseline treatment arm. The "unique" tables count distinct subjects; the "non-unique" tables count rows: total outcome events for the outcome tables, and total person-time intervals for the follow-up tables. The outcome tables are
NAfor a continuous end-of-follow-up outcome, which has no events to count. Seediagnostics().ce.modellist of competing event models if
compeventis specified, NA otherwise
An internal S4 class to carry around parameters during the SEQuential process - inherits user facing parameters from SEQopts
Description
An internal S4 class to carry around parameters during the SEQuential process - inherits user facing parameters from SEQopts
Slots
datapre expansion data
DTpost expansion data
idid column as defined by the user
timetime column as defined by the user
eligibleeligible column as defined by the user
treatmenttreatment column as defined by the user
time_varyinglist of time varying columns as defined by the user
fixedlist of fixed columns as defined by the user
methodmethod of analysis as defined by the user
SEQuential trial emulation
Description
SEQuential is an all-in-one API to SEQuential analysis, returning a SEQoutput object of results. More specific examples can be found on pages at https://causalinference.github.io/SEQTaRget/
Usage
SEQuential(
data,
id.col,
time.col,
eligible.col,
treatment.col,
outcome.col,
time_varying.cols = list(),
fixed.cols = list(),
method,
options,
verbose = TRUE
)
Arguments
data |
data.frame or data.table, will perform expansion according to arguments passed through the |
id.col |
String: column name of the id column |
time.col |
String: column name of the time column |
eligible.col |
String: column name of the eligibility column |
treatment.col |
String: column name of the treatment column |
outcome.col |
String: column name of the outcome column |
time_varying.cols |
List: column names for time varying columns |
fixed.cols |
List: column names for fixed columns |
method |
String: method of analysis to perform; should be one of |
options |
List: optional list of parameters from |
verbose |
Logical: if TRUE, cats progress to console, default is |
Details
Implementation of sequential trial emulation for the analysis of observational databases.
The SEQuential software accommodates time-varying treatments and confounders, as well as binary
and failure time outcomes. SEQuential allows to compare both static and dynamic strategies,
can be used to estimate observational analogs of intention-to-treat
and per-protocol effects, and can adjust for potential selection bias induced by losses-to-follow-up.
Value
An S4 object of class SEQoutput. If options = SEQopts(expand.only = TRUE), returns the expanded data.table directly, with analysis steps skipped.
Examples
data <- SEQdata
# Intention-to-treat (ITT) effect: subjects are assigned to the treatment
# arm defined by their baseline treatment and followed regardless of any later
# treatment changes, so no weighting is required.
SEQuential(data, id.col = "ID",
time.col = "time",
eligible.col = "eligible",
treatment.col = "tx_init",
outcome.col = "outcome",
time_varying.cols = c("N", "L", "P"),
fixed.cols = "sex",
method = "ITT",
options = SEQopts())
# Per-protocol effect via artificial censoring: subjects are censored when they
# deviate from their assigned strategy, and inverse-probability-of-censoring
# weights adjust for the resulting selection bias. The denominator models the
# probability of remaining uncensored given the time-varying confounders, while
# the numerator uses only the baseline covariates to stabilize the weights (so
# the two formulas must differ - identical formulas give weights of 1).
SEQuential(data, id.col = "ID",
time.col = "time",
eligible.col = "eligible",
treatment.col = "tx_init",
outcome.col = "outcome",
time_varying.cols = c("N", "L", "P"),
fixed.cols = "sex",
method = "censoring",
options = SEQopts(weighted = TRUE,
numerator = "sex",
denominator = "N + L + P + sex"))
# End-of-follow-up outcome: rather than a time-to-event, the outcome is read
# once per trial-period at follow-up time 12 and averaged within each baseline
# arm, weighted by the weight at that time. Trial-periods with no measurement
# at exactly 12 fall back to the nearest one within 12 +/- 3; any with none
# in that window are censored out of the average. Use end_of_fup.type =
# "continuous" for a continuous outcome, which is reported as a mean.
eof <- SEQuential(data, id.col = "ID",
time.col = "time",
eligible.col = "eligible",
treatment.col = "tx_init",
outcome.col = "outcome",
time_varying.cols = c("N", "L", "P"),
fixed.cols = "sex",
method = "ITT",
options = SEQopts(end_of_fup = TRUE,
end_of_fup.time = 12,
end_of_fup.type = "binary",
end_of_fup.window = 3,
bootstrap = TRUE,
bootstrap.nboot = 5))
end_of_fup(eof)
An internal S4 class to help transfer weight statistics out of internal_weights
Description
An internal S4 class to help transfer weight statistics out of internal_weights
Slots
weightsa data.table containing the estimated weights, either pre or post expansion
coef.n0numerator zero model
coef.n1numerator one model
coef.d0denominator zero model
coef.d1denominator one model
coef.ncensenumerator censoring model
coef.dcensedenominator censoring model
Bake fixed knots into any ns(followup, df = N) term in params@covariates
Description
splines::ns() recomputes knots from whatever data it sees, so without fixed
knots the basis at prediction time differs from the basis used at fit time.
This helper rewrites every ns(followup, df = N) token in
params@covariates to an explicit ns(followup, knots = c(...), Boundary.knots = c(...))
computed once from the full expanded followup column. The result is a
formula whose model.matrix output is invariant to the row subset passed in.
Usage
bake_followup_spline(params)
Details
Returns the original covariates string unchanged when no ns(followup, df = ...)
token is present (e.g. user supplied custom covariates that already specify
knots).
Build the function that gives each bootstrap copy of a subject a unique ID
Description
Numeric IDs are relabeled arithmetically (orig_id * multiplier + copy
index), but only while every relabeled value stays within the 2^53
exact-integer range of doubles and the IDs are non-negative integers:
beyond 2^53 consecutive copy indices round to the same double, so distinct
bootstrap copies of a subject silently merge under by-ID grouping (e.g.
10-digit IDs). All other cases relabel by string concatenation
(orig_id_b<copy index>).
Usage
bootstrap_id_relabeler(UIDs, n_sample)
Arguments
UIDs |
vector of unique subject IDs |
n_sample |
number of subjects drawn per bootstrap resample |
Value
a function(id_col, idx) returning unique relabeled IDs
Columns referenced by a (possibly per-treatment-level) cache entry
Description
Columns referenced by a (possibly per-treatment-level) cache entry
Usage
cached_cols(cached)
Check a fitted fastglm model for signs of perfect or quasi-complete separation
Description
Issues a warning when separation is detected. Because fastglm uses
IWLS and stops at its iteration limit rather than diverging to Inf,
separation is identified by two complementary signals:
Any coefficient with
|coef| > 25(logit > 25 implies P > 1 - 1e-11, unreachable without separation).Non-finite coefficients (
Inf/-Inf/NaN), which can occur with other solvers.
Usage
check_separation(model, label = "logistic regression")
Arguments
model |
a fastglm model object |
label |
a short string identifying the model (used in the warning message) |
Strip large components from a model object returned by fit_glm
Description
Strip large components from a model object returned by fit_glm
Usage
clean_fastglm(model)
Arguments
model |
a model object (fastglm or parglm.fit) |
Strip fitted-model bulk from a bootstrap iteration's result
Description
No-op in end_of_fup mode, which fits no outcome model.
Usage
clean_models(out, params)
Function to return competing event models from a SEQuential object
Description
Function to return competing event models from a SEQuential object
Usage
compevent(object)
Arguments
object |
SEQoutput object |
Value
A fastglm object, or a named list of fastglm objects when subgroups are specified
Retrieves Outcome, Numerator, and Denominator Covariates
Description
Retrieves Outcome, Numerator, and Denominator Covariates
Usage
covariates(object)
Arguments
object |
object of class SEQoutput |
Value
List of SEQuential covariates
Internal Function to create 'default' loss-to-followup formula
Description
Internal Function to create 'default' loss-to-followup formula
Usage
create.default.LTFU.covariates(params, type)
Internal Function to create 'default' formula
Description
Internal Function to create 'default' formula
Usage
create.default.covariates(params)
Internal Function to create 'default' weighting formula
Description
Internal Function to create 'default' weighting formula
Usage
create.default.weight.covariates(params, type)
Assemble end-of-follow-up estimates and bootstrap confidence intervals
Description
Mirrors create.risk(): eof.data holds the per-arm estimate and
eof.comparison the pairwise between-arm contrasts, both with bootstrap
confidence intervals when bootstrap = TRUE. Contrasts are paired by
bootstrap iteration, so the interval accounts for the correlation between arms.
Usage
create.endoffup(full, boots, params)
Arguments
full |
per-arm estimates from the full-data fit |
boots |
list of per-arm estimates, one per bootstrap iteration |
params |
SEQparams object |
Value
list with eof.data and eof.comparison data.tables
Internal function to pull Risk Ratio and Risk Difference from data when km.curves = TRUE
Description
Internal function to pull Risk Ratio and Risk Difference from data when km.curves = TRUE
Usage
create.risk(data, params, boot_risks = NULL)
Retrieves Denominator Models from SEQuential object
Description
Retrieves Denominator Models from SEQuential object
Usage
denominator(object)
Arguments
object |
object of class SEQoutput |
Value
List of both denominator models
Function to return diagnostic tables from a SEQuential object
Description
Function to return diagnostic tables from a SEQuential object
Usage
diagnostics(object)
Arguments
object |
SEQoutput object |
Value
A named list of diagnostic tables, each broken down by baseline treatment arm. The "unique" and "non-unique" variants count different things:
-
outcome.unique/outcome.nonunique: distinct subjects who had the outcome vs. the total number of outcome events. These coincide for a one-time (terminal) outcome, since each subject contributes at most one event row. Both areNAfor a continuous end-of-follow-up outcome, which has no events to count. -
eof.unique/eof.nonunique: present only whenend_of_fup = TRUE, accounting for every trial-period at the end-of-follow-up time across four mutually exclusive categories - measuredAt k, measuredIn window,Excluded (outside window)andExcluded (no measurement)- against theEligibletotal. The non-unique (trial-period) counts partitionEligible, andAt kplusIn windowequals the trial-periods contributing to the estimate. The unique (subject) counts need not sum toEligible, since one subject can fall into different categories for different trials. For a continuous outcomeeof.summaryadditionally reports the N, mean and SD of the raw analysed measurements per arm, standing in for the suppressed outcome count tables. -
followup.unique/followup.nonunique: distinct subjects contributing follow-up vs. the total number of person-time intervals (expanded rows). The non-unique count is much larger because each subject contributes one row per follow-up period; it is the denominator that, withoutcome.nonunique, gives the per-arm event rate.
Extract the end-of-follow-up outcome estimates
Description
Available when SEQuential() was run with end_of_fup = TRUE. The
estimate in each arm is the weighted average of the outcome measured at
end_of_fup.time, weighted by the period-trial-specific weight at the
time the measurement was taken.
Usage
end_of_fup(object)
Arguments
object |
SEQoutput object |
Value
A named list, one element per subgroup, each a list of two data.tables:
-
estimates: the weighted proportion (binary) or mean (continuous) in each baseline treatment arm, with its bootstrap confidence interval, the trial-periods eligible in each arm, partitioned into those analysed, those censored for want of a measurement in the window - measured at some point but not within[k - window, k + window]- and those never measured at all, with the censoring also as a percentage of the eligible total.Subjectscounts the distinct contributing subjects. -
comparison: the pairwise between-arm difference - in proportions for a binary outcome, in means for a continuous one - with its bootstrap standard error and confidence interval, paired by iteration so the interval accounts for the correlation between arms. For a binary outcome the ratio of proportions is also given, with a confidence interval computed on the log scale and alog(Ratio) SEfor inverse-variance pooling. A ratio is not reported for a continuous outcome, where the outcome need not be bounded away from zero.
Account for every trial-period at the end-of-follow-up time
Description
Classifies each trial-period in the analysis data into exactly one of four mutually exclusive categories, so that the trial-periods contributing to the estimate can be reconciled against those excluded:
measured at
k- contributes, using the measurement at exactlyend_of_fup.time;measured in the window - contributes, having no measurement at
kbut one within[k - window, k + window];excluded, outside the window - has a measurement somewhere, but none within the window;
excluded, no measurement - has no non-missing outcome at any follow-up time. Under
method = "censoring"this includes trial-periods artificially censored before any measurement was taken.
Usage
endoffup.counts(DT, params, type)
Arguments
DT |
expanded data.table, weighted or not - as passed to |
params |
SEQparams object |
type |
either |
Details
Counted over the same data the estimate is computed from, so the first two
categories always sum to the contributing trial-periods reported by
end_of_fup().
Value
named list of data.tables, one element per subgroup, each with a row per baseline treatment arm
Weighted end-of-follow-up average within each treatment arm
Description
Weight truncation (weight.lower / weight.upper, including the
bounds weight.p99 resolves to) is applied here as it is for the
outcome model, since this average is the estimator in end_of_fup mode.
Usage
endoffup.estimate(DT, params)
Arguments
DT |
expanded data.table for one bootstrap iteration |
params |
SEQparams object |
Details
Alongside the estimate this counts the trial-periods censored for want of a
measurement in the window - those measured at some point but not within
[k - window, k + window] - so that share can be reported next to the
estimate they were dropped from. Trial-periods never measured at all are
counted separately rather than folded in, so the analysed, censored and
never-measured counts partition the eligible total. Trial-periods are the unit
because one subject can be analysed in one trial and censored in another.
Value
named list of per-arm data.tables, one element per subgroup
Select the end-of-follow-up outcome measurement for each trial-period
Description
An end-of-follow-up outcome is measured once, at follow-up time
end_of_fup.time (k), rather than as a time-to-event. For each
(id, trial) this returns the single row the estimate is read from:
the measurement at exactly k when one exists, otherwise - if
end_of_fup.window is non-zero - the measurement nearest to k
within [k - window, k + window], with ties (measurements equally far
either side of k) broken toward the later one, so that at least
k of follow-up has elapsed. Trial-periods with no
measurement anywhere in the window contribute no row, i.e. they are censored
out of the estimate.
Usage
endoffup.measure(DT, params)
Arguments
DT |
expanded data.table, weighted (carrying a |
params |
SEQparams object |
Details
Rows carrying a missing outcome are not measurements: under
method = "censoring" these are the artificially censored (treatment
switch) rows, so a subject who deviates before k is correctly excluded
rather than contributing a carried-forward value.
Value
data.table with one row per contributing (id, trial): the outcome value, the weight at that time, the baseline treatment arm, and the follow-up time the measurement was taken at
Per-arm summary of the analysed end-of-follow-up measurements
Description
N, mean and SD of the raw selected measurements per baseline arm - the unweighted analogue of the outcome count tables, reported for continuous outcomes where event counts have no meaning.
Usage
endoffup.summary(DT, params)
Arguments
DT |
expanded data.table, weighted or not - as passed to |
params |
SEQparams object |
Value
named list of data.tables, one element per subgroup
Fit a GLM using the package specified in params@glm.package
Description
Fit a GLM using the package specified in params@glm.package
Usage
fit_glm(X, y, family, weights = NULL, params, start = NULL)
Arguments
X |
model matrix |
y |
response vector |
family |
family object (e.g. quasibinomial()) |
weights |
optional prior weights vector |
params |
SEQparams object |
Count follow-up per treatment arm
Description
Summarises follow-up in each treatment arm, grouped by the baseline treatment
value, restricted to expanded-data rows with an observed (non-NA) outcome -
the person-time the outcome/survival model is fit on. Rows censored under
method = "censoring" (which carry outcome = NA) are excluded,
matching the analysis.
Usage
followup.table(params, type, filter = NA)
Arguments
params |
SEQparams object (uses the expanded |
type |
either |
filter |
subgroup value to restrict to, or |
Details
type = "nonunique" counts follow-up intervals (rows), i.e. total
person-time; dividing the non-unique outcome counts by these gives the per-arm
event rate. type = "unique" counts the distinct subjects contributing
follow-up to the arm (a subject contributing several trials to the same arm is
counted once; a subject who appears in both arms is counted in each).
Value
data.table with the baseline-treatment column and n (count)
Nicely cleans time for readability
Description
Nicely cleans time for readability
Usage
format_time(seconds)
Extract underlying column names from RHS formula strings
Description
Wraps all.vars(as.formula(...)) so that function-wrapped terms in
formula strings (e.g. ns(followup, df = 4), I(x^2), factor(grp))
resolve to their underlying variable names rather than being treated
as raw column names.
Usage
formula_vars(x)
Arguments
x |
character vector of RHS formula strings (may contain |
Value
character vector of unique variable names referenced by x.
Function to return hazard ratios from a SEQuential object
Description
Function to return hazard ratios from a SEQuential object
Usage
hazard_ratio(object)
Arguments
object |
SEQoutput object |
Value
A named vector of hazard ratios, or a named list of vectors when subgroups are specified
Create formula cache
Description
Create formula cache
Usage
init_formula_cache(params)
Arguments
params |
parameter from SEQuential |
Helper Function to inline predict a fastglm object
Description
Helper Function to inline predict a fastglm object
Usage
inline.pred(
model,
newdata,
params,
type = NULL,
case = "default",
multi = FALSE,
target = NULL,
cache = NULL
)
Arguments
model |
a fastglm object |
newdata |
filler for a .SD from data.table |
params |
parameter from SEQuential |
type |
type of prediction |
case |
case type: "default", "LTFU", "visit", "surv" |
multi |
multinomial flag |
target |
target level for multinomial |
cache |
optional formula cache from init_formula_cache |
Internal analysis tool for handling parallelization/bootstrapping on multiple OS types
Description
Internal analysis tool for handling parallelization/bootstrapping on multiple OS types
Usage
internal.analysis(params)
Generic function to format a dataset for hazard ratio calculation
Description
Generic function to format a dataset for hazard ratio calculation
Usage
internal.hazard(model, params, cache)
Internal function for fitting outcome models
Description
Internal function for fitting outcome models
Usage
internal.model(data, params, start = NULL)
Plotting for survival curves
Description
Plotting for survival curves
Usage
internal.plot(survival.data, params)
Arguments
survival.data |
Dataframe containing survival information |
params |
Params passed around SEQuential |
Internal function for creating survival curves
Description
Internal function for creating survival curves
Usage
internal.survival(params, outcome)
Internal function for defining weights
Description
Internal function for defining weights
Usage
internal.weights(DT, data, params, cache)
Arguments
DT |
data.table after expansion |
data |
data.table for data before expansion |
params |
object of class SEQparams (defined in SEQuential) |
cache |
cache |
Function to print Kaplan-Meier curves
Description
Function to print Kaplan-Meier curves
Usage
km_curve(
object,
plot.type = "survival",
plot.title,
plot.subtitle,
plot.labels,
plot.colors
)
Arguments
object |
SEQoutput object to plot |
plot.type |
character: type of plot to print; one of: |
plot.title |
character: defines the title of the plot |
plot.subtitle |
character: plot subtitle |
plot.labels |
length 2 character: plot labels |
plot.colors |
length 2 character: plot colors |
Value
ggplot object of plot plot.type
Function to return survival data from a SEQuential object
Description
Function to return survival data from a SEQuential object
Usage
km_data(object)
Arguments
object |
SEQoutput object |
Value
A data frame of survival values, or a named list of data frames when subgroups are specified
Helper function for nested logistic
Description
Helper function for nested logistic
Usage
multinomial(X, y, family = quasibinomial(), params)
Helper to predict from the nested logistic
Description
Helper to predict from the nested logistic
Usage
multinomial.predict(model, X, target = NULL)
Helper function to get the summary table from multinomial
Description
Helper function to get the summary table from multinomial
Usage
multinomial.summary(model)
Retrieves Numerator Models from SEQuential object
Description
Retrieves Numerator Models from SEQuential object
Usage
numerator(object)
Arguments
object |
object of class SEQoutput |
Value
List of both numerator models
Retrieves Outcome Models from SEQuential object
Description
Retrieves Outcome Models from SEQuential object
Usage
outcome(object)
Arguments
object |
object of class SEQoutput |
Value
List of all outcome models
Parameter Helper
Description
Parameter Helper
Usage
parameter.setter(
data,
DT,
id.col,
time.col,
eligible.col,
outcome.col,
treatment.col,
time_varying.cols,
fixed.cols,
method,
opts,
verbose
)
Simplifies parameters down for later use
Description
Simplifies parameters down for later use
Usage
parameter.simplifier(params)
Predict from a model fitted by fit_glm
Description
Predict from a model fitted by fit_glm
Usage
predict_model(model, X, type = "response")
Arguments
model |
model object returned by fit_glm |
X |
model matrix for prediction |
type |
"response" or "link" |
Helper function to prepare data for fastglm
Description
Helper function to prepare data for fastglm
Usage
prepare.data_cached(weight, params, type, model, case, cache)
Arguments
weight |
data after undergoing preparation |
params |
parameter from SEQuential |
type |
type of model, e.g. d0 = "denominator" |
model |
model number, e.g. d0 = "zero model" |
case |
case |
cache |
cache |
Output constructor
Description
Output constructor
Usage
prepare.output(
params,
WDT,
outcome,
weights,
hazard,
survival.data,
survival.ce,
risk,
runtime,
info,
eof.data = list(),
eof.comparison = list()
)
Resolve the follow-up times at which to report risk difference / ratio
Description
Each requested time in risk.times is snapped to the latest available
follow-up value at or before it (cumulative incidence is a right-continuous
step function). The maximum follow-up time is always included. A NA
risk.times reports only the maximum follow-up time.
Usage
resolve_risk_times(grid, risk.times)
Arguments
grid |
numeric vector of available follow-up values |
risk.times |
numeric vector of requested follow-up times, or |
Value
sorted unique numeric vector of grid follow-up values to report at
Function to return risk information from a SEQuential object
Description
Function to return risk information from a SEQuential object
Usage
risk_comparison(object)
Arguments
object |
SEQoutput object |
Value
A data frame of risk comparison information at the reported follow-up time(s):
risk ratios and risk differences, and when bootstrapped their confidence
intervals and standard errors. The bootstrap standard errors are reported
regardless of bootstrap.CI_method: RD SE is the standard error of the
risk difference (natural scale) and log(RR) SE is the standard error of
the log risk ratio. For an inverse-variance-weighted meta-analysis across
samples, pool Risk Difference with RD SE, and log(Risk Ratio) with
log(RR) SE (then exponentiate the pooled ratio).
Function to return risk information from a SEQuential object
Description
Function to return risk information from a SEQuential object
Usage
risk_data(object)
Arguments
object |
SEQoutput object |
Value
A data table of risk information at the end of followup
Select the cached weight-model formula for a treatment level
Description
A cache entry made by init_formula_cache() is either a single parsed
formula (a list with a $formula element, shared across treatment
levels) or an unnamed list of parsed formulas, one per
params@treat.level. Returns the entry for level, or the
shared entry (or NULL) unchanged.
Usage
select_cached_level(cached, level, params)
Show method for S4 object - SEQoutput.
Description
Show method for S4 object - SEQoutput.
Usage
## S4 method for signature 'SEQoutput'
show(object)
Arguments
object |
A SEQoutput object - usually generated from |
Value
No return value, sends information about SEQoutput to the console