| Title: | Stagewise Variable Selection for Joint Models of Semi-Competing Risks |
|---|---|
| Description: | Implements stagewise regression for variable selection in joint models of recurrent events and terminal events (semi-competing risks). Supports two model frameworks: the joint frailty model (Cox-type) and the joint scale-change model (AFT-type). Provides cooperative lasso, lasso, and group lasso penalties with cross-validation for tuning parameter selection via cross-fitted estimating equations. |
| Authors: | Jared D. Huling [aut, cre], Lingfeng Huo [aut], Ziren Jiang [aut], Jue Hou [aut], Sy Han (Steven) Chiou [ctb], Chiung-Yu Huang [ctb] |
| Maintainer: | Jared D. Huling <[email protected]> |
| License: | GPL (>= 3) |
| Version: | 0.1.3 |
| Built: | 2026-10-12 10:40:14 UTC |
| Source: | https://github.com/jaredhuling/swjm |
Implements stagewise regression for penalized variable selection in joint models of recurrent events and terminal events (semi-competing risks).
Two model frameworks are supported:
Joint Frailty Model (JFM): Cox-type model where
alpha = recurrence/readmission coefficients (first p elements of theta),
beta = terminal/death coefficients (second p elements).
Joint Scale-Change Model (JSCM): AFT-type model where
alpha = recurrence/readmission coefficients (first p elements of theta),
beta = terminal/death coefficients (second p elements).
Three penalty types are available:
"coop": Cooperative lasso, which encourages shared support
between the recurrence and terminal event coefficient vectors.
"lasso": Standard L1 penalty applied coordinate-wise.
"group": Group lasso, which selects variables jointly across
both processes.
All functions expect a recurrent-event data frame with the following columns:
Subject identifier (integer).
Interval start time.
Interval stop time.
1 for recurrent event, 0 for terminal/censoring row.
1 for death, 0 for alive/censored.
Covariate columns.
Maintainer: Jared D. Huling [email protected]
Authors:
Lingfeng Huo
Ziren Jiang
Jue Hou
Other contributors:
Sy Han (Steven) Chiou [contributor]
Chiung-Yu Huang [contributor]
Evaluates the cumulative baseline hazards for readmission and death at arbitrary time points. For JFM, Breslow-type estimators are used. For JSCM, Nelson-Aalen estimators on the accelerated time scale are used.
baseline_hazard( object, times = NULL, which = c("both", "readmission", "death") )baseline_hazard( object, times = NULL, which = c("both", "readmission", "death") )
object |
An object of class |
times |
Numeric vector of evaluation times. If |
which |
Character. Which baseline hazard(s) to return:
|
A data frame with column time and, depending on
which, cumhaz_readmission and/or cumhaz_death.
dat <- generate_data(n = 50, p = 10, scenario = 1, model = "jfm") cv <- cv_stagewise(dat$data, model = "jfm", penalty = "coop", max_iter = 100) bh <- baseline_hazard(cv) head(bh)dat <- generate_data(n = 50, p = 10, scenario = 1, model = "jfm") cv <- cv_stagewise(dat$data, model = "jfm", penalty = "coop", max_iter = 100) bh <- baseline_hazard(cv) head(bh)
Selects the optimal penalty parameter (lambda) along the stagewise path using K-fold cross-validation with cross-fitted estimating equations.
cv_stagewise( data, model = c("jfm", "jscm"), penalty = c("coop", "lasso", "group"), K = 5L, lambda_seq = NULL, eps = NULL, max_iter = NULL, pp = NULL, estimate_frailty = FALSE, ncores = 1L, standardize = TRUE, lambda_min_ratio = NULL )cv_stagewise( data, model = c("jfm", "jscm"), penalty = c("coop", "lasso", "group"), K = 5L, lambda_seq = NULL, eps = NULL, max_iter = NULL, pp = NULL, estimate_frailty = FALSE, ncores = 1L, standardize = TRUE, lambda_min_ratio = NULL )
data |
A data frame in recurrent-event format. |
model |
Character. Either |
penalty |
Character. One of |
K |
Integer. Number of cross-validation folds (default 5). |
lambda_seq |
Numeric vector. The lambda sequence at which to
evaluate the cross-validation criterion. If |
eps |
Numeric. Step size (passed to |
max_iter |
Integer. Maximum iterations (passed to |
pp |
Integer. Early-stop block size (passed to |
estimate_frailty |
Logical. For JFM only: if |
ncores |
Integer. Number of cores for parallel fold training
(default 1, sequential). Uses |
standardize |
Logical. If |
lambda_min_ratio |
Numeric. Passed to |
An object of class "swjm_cv", a list with components:
Integer, position of best lambda by combined cross-fitted score norm.
Integer, position of best lambda by recurrence score norm.
Integer, position of best lambda by terminal score norm.
Numeric vector of lambda values evaluated.
Combined cross-fitted score norm path.
Recurrence score norm path.
Terminal score norm path.
The full-data stagewise fit (class "swjm_path").
Character.
Character.
dat <- generate_data(n = 50, p = 10, scenario = 1, model = "jfm") fit <- stagewise_fit(dat$data, model = "jfm", penalty = "coop", max_iter = 100) cv_res <- cv_stagewise(dat$data, model = "jfm", penalty = "coop", lambda_seq = fit$lambda, max_iter = 100) cv_resdat <- generate_data(n = 50, p = 10, scenario = 1, model = "jfm") fit <- stagewise_fit(dat$data, model = "jfm", penalty = "coop", max_iter = 100) cv_res <- cv_stagewise(dat$data, model = "jfm", penalty = "coop", lambda_seq = fit$lambda, max_iter = 100) cv_res
Unified interface that dispatches to model-specific data generation functions for the joint frailty model (JFM) or joint scale-change model (JSCM).
generate_data(n, p, scenario = 1, model = c("jfm", "jscm"), ...)generate_data(n, p, scenario = 1, model = c("jfm", "jscm"), ...)
n |
Integer. Number of subjects. |
p |
Integer. Number of covariates (should be a multiple of 10 for scenarios 1–3). |
scenario |
Integer. Scenario for true coefficient configuration (1, 2, 3, or other for a simple default). |
model |
Character. Either |
... |
Additional arguments passed to the model-specific function.
For JFM: |
A list with components:
A data frame in recurrent-event format with columns
id, t.start, t.stop, event,
status, and covariate columns x1, ..., xp.
Numeric vector of true alpha coefficients.
Numeric vector of true beta coefficients.
# JFM data with 30 subjects and 10 covariates dat_jfm <- generate_data(n = 30, p = 10, scenario = 1, model = "jfm") head(dat_jfm$data) # JSCM data with 30 subjects and 10 covariates dat_jscm <- generate_data(n = 30, p = 10, scenario = 1, model = "jscm") head(dat_jscm$data)# JFM data with 30 subjects and 10 covariates dat_jfm <- generate_data(n = 30, p = 10, scenario = 1, model = "jfm") head(dat_jfm$data) # JSCM data with 30 subjects and 10 covariates dat_jscm <- generate_data(n = 30, p = 10, scenario = 1, model = "jscm") head(dat_jscm$data)
Generates recurrent-event and terminal-event data under a Cox-type
joint frailty model. Ported from
Data_Generation_time_dependent_new().
generate_data_jfm( n, p, scenario = 1, b = 6.5, lambda0_d = 0.041, lambda0_r = 1, gamma_frailty = 0, cov_type = c("internal", "external", "fixed") )generate_data_jfm( n, p, scenario = 1, b = 6.5, lambda0_d = 0.041, lambda0_r = 1, gamma_frailty = 0, cov_type = c("internal", "external", "fixed") )
n |
Integer. Number of subjects. |
p |
Integer. Number of covariates. |
scenario |
Integer. Scenario (1, 2, 3, or other). |
b |
Numeric. Upper bound of the censoring uniform distribution (default 6.50). |
lambda0_d |
Numeric. Baseline hazard rate for the terminal event (default 0.041). |
lambda0_r |
Numeric. Baseline hazard rate for recurrent events (default 1). |
gamma_frailty |
Numeric. Frailty variance parameter. When positive,
a subject-specific frailty |
cov_type |
Character. How time-varying covariates are generated:
|
Internally the simulation uses the Rondeau et al. (2007) convention
where alpha governs death and beta governs recurrence.
The returned alpha_true and beta_true are relabelled to
match the package-wide convention:
alpha_true: recurrence (readmission) coefficients.
beta_true: terminal (death) coefficients.
Within each subject the covariates are regenerated at each gap time,
yielding time-dependent covariates. Censoring times are
Uniform(1, b).
A list with components:
Data frame with columns id, t.start,
t.stop, event, status, x1, ...,
xp.
True alpha (terminal) coefficients.
True beta (recurrence) coefficients.
dat <- generate_data_jfm(n = 30, p = 10, scenario = 1) head(dat$data) dat$alpha_true dat$beta_truedat <- generate_data_jfm(n = 30, p = 10, scenario = 1) head(dat$data) dat$alpha_true dat$beta_true
Generates recurrent-event and terminal-event data under an AFT-type
joint scale-change model using simGSC.
Ported from Data_gen_reReg().
generate_data_jscm(n, p, scenario = 1, b = 4)generate_data_jscm(n, p, scenario = 1, b = 4)
n |
Integer. Number of subjects. |
p |
Integer. Number of covariates. |
scenario |
Integer. Scenario (1, 2, 3, or other). |
b |
Numeric. Upper bound of the censoring uniform distribution (default 4). |
In the JSCM convention:
alpha governs the recurrence process.
beta governs the terminal (death) process.
Covariates are drawn from Uniform(-1, 1). A gamma frailty with
shape = 4, scale = 1/4 is used. Censoring times are
Uniform(0, b).
A list with components:
Object returned by simGSC (a
data frame with recurrent-event structure).
True alpha (recurrence) coefficients.
True beta (terminal) coefficients.
dat <- generate_data_jscm(n = 30, p = 10, scenario = 1) head(dat$data) dat$alpha_true dat$beta_truedat <- generate_data_jscm(n = 30, p = 10, scenario = 1) head(dat$data) dat$alpha_true dat$beta_true
Plots the cross-validated estimating-equation score norms versus
, with separate lines for the readmission and death
components. A vertical dashed line marks the lambda that minimizes the
combined norm. The top axis shows the total number of active variables
along the path.
## S3 method for class 'swjm_cv' plot(x, log_lambda = TRUE, ...)## S3 method for class 'swjm_cv' plot(x, log_lambda = TRUE, ...)
x |
An object of class |
log_lambda |
Logical. If |
... |
Currently unused. |
Invisibly returns x.
dat <- generate_data(n = 50, p = 10, scenario = 1, model = "jfm") cv <- cv_stagewise(dat$data, model = "jfm", penalty = "coop", max_iter = 200) plot(cv)dat <- generate_data(n = 50, p = 10, scenario = 1, model = "jfm") cv <- cv_stagewise(dat$data, model = "jfm", penalty = "coop", max_iter = 200) plot(cv)
Produces a glmnet-style plot of coefficient trajectories versus
along the stagewise regularization path.
Two panels are drawn by default: one for the readmission sub-model
(alpha) and one for the death sub-model (beta). The top axis of
each panel shows the number of active variables at that lambda.
## S3 method for class 'swjm_path' plot( x, log_lambda = TRUE, which = c("both", "readmission", "death"), col = NULL, ... )## S3 method for class 'swjm_path' plot( x, log_lambda = TRUE, which = c("both", "readmission", "death"), col = NULL, ... )
x |
An object of class |
log_lambda |
Logical. If |
which |
Character. Which sub-model(s) to plot:
|
col |
Optional vector of colors, one per covariate. Recycled if
shorter than |
... |
Currently unused. |
Invisibly returns x.
dat <- generate_data(n = 50, p = 10, scenario = 1, model = "jfm") fit <- stagewise_fit(dat$data, model = "jfm", penalty = "coop", max_iter = 200) plot(fit)dat <- generate_data(n = 50, p = 10, scenario = 1, model = "jfm") fit <- stagewise_fit(dat$data, model = "jfm", penalty = "coop", max_iter = 200) plot(fit)
Produces a figure for a "swjm_pred" object. The layout depends on
the model:
## S3 method for class 'swjm_pred' plot( x, which_subject = 1L, which_process = c("both", "readmission", "death"), threshold = 0, ... )## S3 method for class 'swjm_pred' plot( x, which_subject = 1L, which_process = c("both", "readmission", "death"), threshold = 0, ... )
x |
An object of class |
which_subject |
Integer. Index of the subject to highlight (default
|
which_process |
Character. Which sub-model(s) to plot:
|
threshold |
Non-negative numeric. Only predictors whose absolute
subject-specific contribution exceeds this value are shown in the bar
chart. The default |
... |
Currently unused. |
JFM (four panels):
Readmission-free survival curves for all subjects, with the selected subject highlighted.
Bar chart of readmission predictor contributions
(log-hazard scale).
Death-free survival curves with the selected subject highlighted.
Bar chart of death predictor contributions .
JSCM (four panels):
Recurrent-event survival curves (AFT model) with the selected
subject highlighted. The panel title shows the total acceleration
factor .
Bar chart of recurrence log time-acceleration contributions
: positive = events sooner, negative = later.
Death-free survival curves with the selected subject highlighted,
total acceleration factor in the title.
Bar chart of terminal-event log time-acceleration contributions
.
In all cases bars represent subject-specific contributions
(coefficient covariate value), not bare coefficients, so the
display correctly reflects how much each predictor shifts the log-hazard
(JFM) or log time-acceleration (JSCM) for this particular subject.
Invisibly returns x.
dat <- generate_data(n = 50, p = 10, scenario = 1, model = "jfm") cv <- cv_stagewise(dat$data, model = "jfm", penalty = "coop", max_iter = 100) newz <- matrix(rnorm(30), nrow = 3, ncol = 10) pred <- predict(cv, newdata = newz) plot(pred, which_subject = 2) plot(pred, which_subject = 2, threshold = 0.05)dat <- generate_data(n = 50, p = 10, scenario = 1, model = "jfm") cv <- cv_stagewise(dat$data, model = "jfm", penalty = "coop", max_iter = 100) newz <- matrix(rnorm(30), nrow = 3, ncol = 10) pred <- predict(cv, newdata = newz) plot(pred, which_subject = 2) plot(pred, which_subject = 2, threshold = 0.05)
Computes subject-specific predictions from a cross-validated swjm_cv
fit. The output differs by model:
## S3 method for class 'swjm_cv' predict(object, newdata, times = NULL, ...)## S3 method for class 'swjm_cv' predict(object, newdata, times = NULL, ...)
object |
An object of class |
newdata |
A numeric matrix or data frame of covariate values.
Must have |
times |
Numeric vector of evaluation times (JFM only). If
|
... |
Currently unused. |
JFM — returns survival curves for both processes using the Breslow
cumulative baseline hazards. For subject with covariate vector
:
JSCM — returns survival curves for both processes using a
Nelson-Aalen baseline on the accelerated time scale. For subject :
The linear predictor is a log time-acceleration
factor: the recurrence process for subject runs on a time axis
scaled by relative to the baseline. Each
predictor contributes to this log-scale factor,
so is the multiplicative factor on the time
scale attributable to predictor alone. Values greater than 1
accelerate events (shorter times); values less than 1 decelerate them
(longer times).
An object of class "swjm_pred", a list with:
Matrix of readmission-free survival probabilities
(rows = subjects, columns = times).
Matrix of death-free survival probabilities.
Numeric vector of evaluation times.
Linear predictors for readmission
(). For JSCM this is the log
time-acceleration for the recurrence process.
Linear predictors for death ().
For JSCM this is the log time-acceleration for the terminal process.
(JSCM only) : the
multiplicative factor by which the recurrence time axis is scaled
relative to baseline. NULL for JFM.
(JSCM only) Analogous time-acceleration factor
for the terminal process. NULL for JFM.
Matrix of per-predictor contributions
(rows = subjects, columns = covariates).
For JFM these are log-hazard contributions; for JSCM they are
log time-acceleration contributions.
Analogous matrix for the terminal process.
dat <- generate_data(n = 50, p = 10, scenario = 1, model = "jfm") cv <- cv_stagewise(dat$data, model = "jfm", penalty = "coop", max_iter = 100) newz <- matrix(rnorm(30), nrow = 3, ncol = 10) pred <- predict(cv, newdata = newz) plot(pred) dat_jscm <- generate_data(n = 50, p = 10, scenario = 1, model = "jscm") cv_jscm <- cv_stagewise(dat_jscm$data, model = "jscm", penalty = "coop", max_iter = 500) pred_jscm <- predict(cv_jscm, newdata = newz) plot(pred_jscm)dat <- generate_data(n = 50, p = 10, scenario = 1, model = "jfm") cv <- cv_stagewise(dat$data, model = "jfm", penalty = "coop", max_iter = 100) newz <- matrix(rnorm(30), nrow = 3, ncol = 10) pred <- predict(cv, newdata = newz) plot(pred) dat_jscm <- generate_data(n = 50, p = 10, scenario = 1, model = "jscm") cv_jscm <- cv_stagewise(dat_jscm$data, model = "jscm", penalty = "coop", max_iter = 500) pred_jscm <- predict(cv_jscm, newdata = newz) plot(pred_jscm)
Unified interface for stagewise variable selection in joint models of recurrent events and terminal events. Dispatches to model-specific implementations for the Joint Frailty Model (JFM) or Joint Scale-Change Model (JSCM).
stagewise_fit( data, model = c("jfm", "jscm"), penalty = c("coop", "lasso", "group"), eps = NULL, max_iter = NULL, pp = NULL, estimate_frailty = FALSE, standardize = TRUE, lambda_min_ratio = NULL )stagewise_fit( data, model = c("jfm", "jscm"), penalty = c("coop", "lasso", "group"), eps = NULL, max_iter = NULL, pp = NULL, estimate_frailty = FALSE, standardize = TRUE, lambda_min_ratio = NULL )
data |
A data frame in recurrent-event format with columns
|
model |
Character. Either |
penalty |
Character. One of |
eps |
Numeric. Base step size for the stagewise update, used at the top
of the regularization path. The step is divided by ten each time the dual
norm falls a further decade, so |
max_iter |
Integer. Maximum number of stagewise iterations. |
pp |
Integer. Early-stopping block size: algorithm checks every
|
estimate_frailty |
Logical. For JFM only: if |
standardize |
Logical. If |
lambda_min_ratio |
Numeric. The path stops once the dual norm falls
below this fraction of its value at the top of the path. Past that point
the coefficients are essentially static, so the remaining iterations cost
time without changing the fit. If |
An object of class "swjm_path", a list with components:
Number of iterations performed.
Character, why the path terminated:
"max_iter" (ran to the iteration cap),
"early_stop" (a single coordinate dominated every update in
the last pp iterations), or "lambda_min_ratio" (the
dual norm fell below lambda_min_ratio times its initial
value).
Integer, the iteration cap used for the fit.
Matrix of coefficient paths (2p rows by
k+1 columns).
Numeric vector of penalty parameter approximations at each iteration.
Numeric vector of penalty norm values along the path.
Character, the model used.
Character, the penalty used.
dat <- generate_data(n = 50, p = 10, scenario = 1, model = "jfm") fit <- stagewise_fit(dat$data, model = "jfm", penalty = "coop", max_iter = 100) fitdat <- generate_data(n = 50, p = 10, scenario = 1, model = "jfm") fit <- stagewise_fit(dat$data, model = "jfm", penalty = "coop", max_iter = 100) fit