Given cross-validated predictions from multiple TWAS weight methods, learns non-negative combination coefficients (summing to 1) via constrained least squares. Returns ensemble weights and per-method performance metrics.
Usage
ensembleWeights(
cvResults,
Y,
twasWeightList = NULL,
contextIndex = 1,
solver = c("quadprog", "nnls", "lbfgsb", "glmnet"),
alpha = 1
)Arguments
- cvResults
Output of
twasWeightsCv, with$prediction(named list of method -> out-of-fold prediction matrix, keys like"susie_predicted"). For multi-dataset: a list of such objects.- Y
Observed outcome vector or matrix (samples x contexts). For multi-dataset: a list of vectors/matrices, one per dataset.
- twasWeightList
Optional named list of weight matrices from
learnTwasWeights, with keys like"susie_weights". Used to construct the final combined TWAS weight vector. For multi-dataset: a list of such lists (the first is used as the weight template).- contextIndex
Integer indicating which column of Y to use when Y is a matrix. Default is 1 (univariate).
- solver
Character string specifying the optimization backend. One of
"quadprog"(default),"nnls","lbfgsb", or"glmnet"."quadprog"solves a constrained QP with sum-to-1 and non-negativity constraints."nnls"uses non-negative least squares (Lawson-Hanson algorithm, as in SuperLearner) and normalizes post-hoc."lbfgsb"usesoptim(method = "L-BFGS-B")with non-negativity bounds and normalizes post-hoc."glmnet"usescv.glmnetwithlower.limits = 0for penalized non-negative regression, providing automatic method selection via regularization. All solvers fall back to equal weights on failure.- alpha
Elastic net mixing parameter, used only when
solver = "glmnet".alpha = 1(default) is lasso (sparse method selection),alpha = 0is ridge, and intermediate values give elastic net.
Value
A list with components:
- methodCoef
Named numeric vector of combination coefficients (\(\zeta_k\)), non-negative and summing to 1. Names are method base names (e.g.,
"susie","enet").- ensembleTwasWeights
Final combined weight vector \(w = \sum_k \zeta_k w_k\), or NULL if
twasWeightListis not provided. Returned as a vector for univariate Y, matrix otherwise.- methodPerformance
Named numeric vector of per-method R-squared computed from out-of-fold CV predictions. Preserved so users can still report individual method performance.
Details
This implements the stacked regression approach of SR-TWAS (Dai et al., Nature Communications, 2024, doi:10.1038/s41467-024-50983-w ). The ensemble provides a principled way to combine predictions from many TWAS weight methods without requiring the user to pick one method a priori or pay a multiple-testing penalty for running several.
For single-dataset usage, pass one twasWeightsCv() result directly.
For multi-dataset ensemble (e.g., combining cell types or reference panels
such as CUMC1 + MIT), pass a list of twasWeightsCv() results along
with a list of observed Y vectors - this learns a single joint set of
coefficients.
The stacked regression solves:
$$\min_{\zeta} \|y - P\zeta\|^2 \quad \text{s.t.} \quad \zeta_k \geq 0,\ \sum_k \zeta_k = 1$$
where P is the \(n \times K\) matrix of out-of-fold predictions from K
methods. Four solver backends are available: "quadprog" enforces
both constraints during optimization; "nnls", "lbfgsb", and
"glmnet" enforce non-negativity only, then normalize coefficients
to sum to 1. The "glmnet" solver additionally applies
regularization, which can produce sparse solutions (method selection).
If any solver fails, the function falls back to equal weights with a
warning.
Methods whose CV predictions have zero variance (e.g., when all weights are zero) are excluded from the optimization and assigned \(\zeta_k = 0\).
Predictions and Y are aligned by sample names (rownames) when available, rather than assuming positional order.
Examples
if (FALSE) { # \dontrun{
# After running twasWeightsPipeline with CV:
res <- twasWeightsPipeline(X, y, cvFolds = 5, weightMethods = methods)
ens <- ensembleWeights(
cvResults = res$twasCvResult,
Y = y,
twasWeightList = res$twasWeights
)
ens$methodCoef # combination weights, sum to 1
# Multi-dataset ensemble (e.g., CUMC1 + MIT cell types):
ens_multi <- ensembleWeights(
cvResults = list(res_cumc$twasCvResult, res_mit$twasCvResult),
Y = list(y_cumc, y_mit),
twasWeightList = list(res_cumc$twasWeights, res_mit$twasWeights)
)
} # }