
Build a Reusable Stratified Cox Data Cache (C++ Backend)
Source:R/helper_glm_fit.R
build_stratified_cox_data_cache_cpp.RdPrecomputes and caches, per stratum, the sorted risk-set structure needed
to evaluate the stratified Cox partial-likelihood, score, and Hessian, so
that repeated Newton-Raphson or L-BFGS fits on the same
(X, y, dead, strata) data (e.g. across bootstrap/randomization
replicates of the treatment column) do not repeat the per-stratum sort and
event-time tabulation on every call. This is the stratified counterpart of
build_cox_data_cache_cpp; the returned cache is consumed by
fast_coxph_regression_prebuilt_cpp, which implements the
same partial-likelihood family as fast_coxph_regression and
fast_coxph_regression_cpp, extended to sum the log-partial-
likelihood, score, and Hessian across independent strata-specific risk
sets while sharing a single regression coefficient vector \(\beta\)
across all strata (a shared-\(\beta\), per-stratum-baseline-hazard
stratified Cox model).
Arguments
- X
A numeric matrix of predictor variables (no intercept column); \(n\) rows, one per subject.
- y
A numeric vector of length \(n\) giving the observed (event or censoring) time for each subject.
- dead
A numeric vector of length \(n\) with values in
{0, 1}indicating event status (1 = event/death, 0 = right-censored).- strata
An integer vector of length \(n\) giving the stratum (block/cluster) label of each subject. Risk sets are formed separately within each distinct label.
Value
An externalptr to a cached, per-stratum sorted Cox
risk-set representation of (X, y, dead, strata), for use as the
cox_data_xptr argument of
fast_coxph_regression_prebuilt_cpp.
Details
Model. No fitting happens here; this function only partitions
subjects into per-stratum risk sets and prepares each one for the
Breslow-tied stratified Cox partial likelihood
$$\ell(\beta) = \sum_{s} \sum_{k \in s} \Big[ \big(\textstyle\sum_{i \in D_{sk}} x_i\big)^\top \beta - d_{sk} \log\!\big(\textstyle\sum_{j \in R_{sk}} e^{x_j^\top \beta}\big) \Big],$$
where the outer sum runs over strata \(s\) (distinct baseline hazards),
\(D_{sk}\) is the set of subjects with an event at the \(k\)-th unique
event time within stratum \(s\), and \(R_{sk}\) is the corresponding
within-stratum risk set (subjects in stratum \(s\) with y >=
that event time). Risk sets never cross strata, so subjects are only ever
compared to other subjects in the same stratum; \(\beta\) is shared
across strata while the baseline hazard is allowed to differ arbitrarily
by stratum. See fast_coxph_regression for the unstratified
model, scale, and optimizer contract; this page documents only the
per-stratum cache construction.
What is cached. Subjects are grouped into strata by their
integer strata label (via an ordered std::map<int, ...>,
so strata are processed and stored in ascending label order). Within each
stratum, a CoxData record is built exactly as in
build_cox_data_cache_cpp: subjects are sorted by ascending
y, ties broken by placing events before censored observations,
and the per-stratum unique event times and tied-event counts
(event_counts) are tabulated to drive the within-stratum Breslow
tie-handling correction.
Input conventions. X is an \(n \times p\) design matrix
with one row per subject and no intercept column. y is
the observed time (event or censoring time) and dead is a 0/1
event indicator (1 = event, 0 = right-censored); both have length
\(n\) matching nrow(X). strata is a length-\(n\)
integer vector of stratum (block/cluster) labels; labels need not be
contiguous or start at 1, and a stratum with a single subject or with no
observed events contributes an empty or degenerate risk set that carries
no information to the partial likelihood, score, or Hessian (its rows
are still stored, but they will not affect the fit). Callers are
expected to have already dropped uninformative strata upstream (see
get_informative_rows() in the stratified-Cox inference class) when
that matters for numerical stability; this function does not filter
strata itself. As with build_cox_data_cache_cpp, tied
event times use the Breslow approximation, there is no support for left-
or interval-censored data at this layer, and NA/non-finite values
in X, y, dead, or strata are not checked or
handled here.
Return value and object lifetime. Returns an externalptr
(Rcpp::XPtr) wrapping a heap-allocated
std::vector<CoxData> with one element per distinct stratum label
(ordered ascending by label), consumed by
fast_coxph_regression_prebuilt_cpp exactly like the length-1
vector returned by build_cox_data_cache_cpp. Lifetime,
garbage-collection, and non-serializability semantics are identical to
build_cox_data_cache_cpp: the cache is immutable once
built and safe to reuse across repeated fits as long as X,
y, dead, and strata have not changed; callers (e.g.
InferenceStratifiedCoxPH$private$strat_cox_data_cache) are
responsible for invalidating and rebuilding it when the treatment
assignment, covariates, or stratification changes.
Complexity. \(O(n \log(n/S))\) for the per-stratum sorts plus
\(O(n)\) for the tabulation passes, where \(n\) is the number of
subjects and \(S\) is the number of distinct strata; memory use is
\(O(np)\) for the per-stratum row-major copies of X plus
\(O(n)\) for the sorted y/dead and event-time tables.
See also
build_cox_data_cache_cpp for the unstratified
(single risk-set) analog, fast_coxph_regression_prebuilt_cpp
for the fitting routine that consumes this cache, and
fast_coxph_regression for the full Cox model documentation,
including the partial-likelihood derivation, tie-handling, and references.
Analogous Python API:
lifelines CoxPHFitter
(stratified fits via the strata argument) and
statsmodels duration models.