mixle.inference.survival module¶
Time-to-event (survival) estimators and hazard regression.
Survival analysis models the time until an event in the presence of right-censoring (subjects who leave the study before the event – their time is a lower bound, not a missing value). The toolkit here covers the estimators and the regression layer:
kaplan_meier()/nelson_aalen()– nonparametric survival and cumulative-hazard curves with Greenwood / Poisson variance and POINTWISE confidence intervals (per time point; no simultaneous band is implemented).
cox_ph()– the Cox proportional-hazards regression: how covariates multiply the hazard, estimated from the partial likelihood (Efron or Breslow tie handling), with stratification and time-varying covariates (counting-processstart, stopinput), Breslow baseline hazard, and the concordance index.
discrete_time_hazard()(+to_person_period()) – discrete-time hazard models fit as a binary GLM on the person-period array (logit or complementary-log-log), supporting offsets and fixed effects through the design matrix.
aalen_johansen()– competing-risks cumulative incidence functions (cause-specific).
aalen_additive()– Aalen’s additive-hazards regression (cumulative covariate effects).
frailty_cox()– shared gamma-frailty Cox for clustered survival (random effect per group), fit by EM.
Event indicators are 1 for an observed event and 0 for right-censoring (for competing risks, an integer cause label with 0 = censored).
Assumptions shared by everything here, stated once: subjects (or, for the frailty model, groups) are INDEPENDENT, and censoring is NON-INFORMATIVE (independent of the event time given the covariates). Informative censoring – subjects leaving because they are about to fail – biases every estimator in this module, and nothing in the data can detect it; it is a design claim the caller must own.
- kaplan_meier(time, event=None, *, ci_level=0.95)[source]
Kaplan–Meier product-limit estimate of the survival function
S(t).- Parameters:
- Returns:
{'time', 'survival', 'se', 'ci_low', 'ci_high', 'at_risk', 'n_events', 'median'}.- Return type:
ci_low/ci_highare PER-TIME-POINT (pointwise) intervals, not a simultaneous confidence band: each is a MARGINAL, asymptotic (Greenwood log–log) interval forS(t)at its owntwith probabilityci_levelunder independent censoring, but the probability that the true curve stays inside the envelope at EVERY time point is far lower – measured simultaneous coverage of the pointwise 95% envelope is 0.60 / 0.51 / 0.43 at n = 50 / 100 / 200 (it FALLS with n, because more event times mean more chances to escape). Reading the plotted envelope as “the curve lives in here” is a simultaneous claim these intervals do not support; a Hall–Wellner band is the standard tool for that and is not implemented here.
- nelson_aalen(time, event=None)[source]
Nelson–Aalen estimate of the cumulative hazard
H(t) = sum d_i / Y_i.
- class CoxResult(coef, se, cov, loglik, baseline_time, baseline_cumhaz, concordance, n_iter, converged, baseline_by_stratum=<factory>)[source]
Bases:
objectFitted Cox proportional-hazards model.
- Parameters:
- coef
(p,)log-hazard-ratio coefficients.- Type:
- se
(p,)standard errors (inverse observed information).- Type:
- cov
(p, p)covariance.- Type:
- loglik
maximised partial log-likelihood.
- Type:
- baseline_time / baseline_cumhaz
Breslow baseline cumulative hazard for an unstratified fit. These arrays are empty for a multi-stratum fit.
- baseline_by_stratum
mapping from each stratum label to its own
timeandcumhazarrays.- Type:
dict[object, dict[str, numpy.ndarray]]
- concordance
Harrell’s C-index, evaluated only within strata. This is
Nonefor counting-process input unless subject identifiers are supplied.- Type:
float | None
- n_iter
Newton iterations.
- Type:
- converged
whether Newton’s method reached
tolwith a finite, well-identified fit.Falsemeans either it hitmax_iterwithout reachingtol, a step produced a non-finite iterate (kept the last finite one instead), or the final standard errors are enormous – the classic symptom of (quasi-)complete separation, where the partial likelihood has no finite maximizer and Newton’s steps can shrink belowtolwhile the coefficients themselves keep drifting toward infinity.- Type:
- cox_ph(x, time, event, *, start=None, strata=None, subject=None, ties='efron', max_iter=50, tol=1e-9)[source]
Cox proportional-hazards regression by Newton–Raphson on the partial likelihood.
The hazard is
h(t | x) = h0(t) exp(x' beta); only the ordering of event times enters, so the baselineh0is left unspecified (semi-parametric). Time-varying covariates are supported through the counting-process form: passstartso each row is an at-risk interval(start, stop](a subject contributes several rows), and the risk set at an event time is every interval covering it.- Parameters:
x (ndarray) –
(n, p)covariates (no intercept – it is absorbed into the baseline).time (ndarray) –
(n,)event/censoring times (the interval stop times).event (ndarray) –
(n,)1 = event, 0 = censored.start (ndarray | None) – optional
(n,)interval start times for time-varying covariates / left truncation.strata (ndarray | None) – optional
(n,)labels; each stratum gets its own baseline hazard (coefficients shared).subject (ndarray | None) – optional
(n,)subject identifiers. Required to compute concordance for counting-process input with multiple rows per subject.ties (str) –
"efron"(default, more accurate) or"breslow"tie handling.max_iter (int) – Newton controls.
tol (float) – Newton controls.
- Returns:
A
CoxResult.- Return type:
CoxResult
What the standard errors assume – read this before using counting-process input for clustered or recurrent events. The SEs are the inverse observed information of the partial likelihood, which is valid when SUBJECTS are independent. The
(start, stop]interface happily accepts multiple rows per subject (that is its purpose: time-varying covariates for one subject) and also LOOKS like it accepts recurrent events or cluster members as rows – but rows from the same subject/cluster are dependent, the information-based SEs do not know that, and they understate: on a simulated clustered design the mean reported SE was 0.68 of the true sampling SD. For clustered data usefrailty_cox()(models the dependence) or bootstrap over SUBJECTS/CLUSTERS – resampling rows would repeat the same mistake. Proportional hazards itself (covariate effects constant over time) is assumed, not checked: no diagnostic ships in this module, so inspect Schoenfeld-style residuals or stratified log(-log) survival plots externally before readingcoefas a time-constant log-hazard ratio.
- to_person_period(time, event, covariates=None)[source]
Expand right-censored durations into a person-period (long) array for discrete-time models.
Each subject contributes one row per discrete period they were at risk; the binary outcome is 1 in the period the event occurred and 0 otherwise. Integer
timeis the number of periods observed.
- discrete_time_hazard(x, outcome, *, link='cloglog', offset=None)[source]
Discrete-time hazard model: a binary GLM on the person-period array.
Fit on the long-format data from
to_person_period()(the designxtypically holds period indicators / a time trend plus covariates).clogloggives the grouped-proportional-hazards (interval-censored Cox) interpretation;logitgives the proportional-odds hazard.
- aalen_johansen(time, event, *, causes=None)[source]
Aalen–Johansen cumulative incidence functions for competing risks.
With several mutually exclusive event types, the cause-specific CIF
F_k(t)is the probability of failing from causekby timetaccounting for the competing causes (it is not1 - KMon the cause, which overstates incidence).- Parameters:
- Returns:
{'time', 'cif': {cause: array}, 'overall_survival'}.- Return type:
- aalen_additive(x, time, event, *, intercept=True)[source]
Aalen’s additive-hazards regression: cumulative regression functions
B(t).Models
h(t | x) = b0(t) + sum_j x_j b_j(t)with time-varying additive effects. At each event time the incrementdBis the least-squares solution over the risk set; the cumulativeB(t)(returned) has interpretable slopes – a risingB_jmeans covariatejadds hazard.The estimator is only defined while the risk-set design has full column rank, and it degrades BEFORE it breaks: as the risk set shrinks toward
psubjects the least-squares increments are dominated by noise, and the accumulated tail ofB(t)is numerical garbage that LOOKS like a dramatic late effect (measured:max abs(B)growing 1.4 -> 19 over the last few event times of a null design). Estimation therefore STOPS at the first event time whose risk-set design is rank-deficient or numerically ill-conditioned – the standard Aalen practice – instead of silently substituting a minimum-norm solution and accumulating it.truncated_atreports where (None if the full curve was estimable); the curve up to that point is unaffected by the truncation.- Returns:
{'time', 'cum_coef', 'truncated_at'}wherecum_coefis(n_estimated_times, p[+1])cumulative coefficients (the first column is the baseline wheninterceptis True) andtruncated_atis the first event time excluded because the risk-set design lost full rank (Nonewhen no truncation occurred).- Parameters:
- Return type:
- class FrailtyCoxResult(coef, se, theta, frailties, groups, frailty_variance=<factory>, frailty_log_mean=<factory>, n_iter=0, converged=False, ties='breslow', se_method='complete-data')[source]
Bases:
objectShared gamma-frailty Cox result.
- Parameters:
- coef / se
fixed-effect log-hazard-ratios and standard errors (see
se_methodfor what the SEs account for – the default plug-in SEs understate).
- theta
estimated frailty variance. A POINT estimate with no uncertainty attached: no SE or test accompanies it, the null
theta = 0sits on the parameter boundary (a likelihood ratio there is a 50:50 chi2_0/chi2_1 mixture, not implemented), and the EM estimate never actually reaches 0 under a true theta of 0 (measured mean 0.046 on null simulations) – so a small positivethetais what NO clustering looks like, not weak evidence of some.- Type:
- frailties
posterior mean random effect per group.
- Type:
- frailty_variance
posterior variance of each group random effect.
- Type:
- frailty_log_mean
posterior expectation of
log(w_g).- Type:
- groups
group labels aligned to
frailties.- Type:
- n_iter
EM iterations.
- Type:
- converged
whether the EM convergence criterion was met.
- Type:
- se_method
"complete-data"(plug-in information, understates) or"jackknife"(delete-one-group, accounts for frailty/theta estimation).- Type:
- frailty_cox(x, time, event, groups, *, max_iter=50, tol=1e-5, ties='breslow', se_method='complete-data')[source]
Shared gamma-frailty Cox model for clustered survival, by EM.
Subjects in the same group share an unobserved frailty
w_g ~ Gamma(1/theta, 1/theta)(mean 1, variancetheta) that multiplies the hazard, capturing within-group correlation. The E-step retainsE[w_g],Var(w_g), andE[log(w_g)]under the conjugate gamma posterior. The coefficient/baseline M-step usesE[w_g]in the integrated-hazard term, while the dispersion M-step maximises the expected gamma-prior log likelihood using bothE[w_g]andE[log(w_g)].On
theta: it is returned as a point estimate ONLY – see the honesty notes onFrailtyCoxResultbefore reading a small value as evidence for (or against) clustering.- Parameters:
se_method (str) – how the fixed-effect SEs are computed.
"complete-data"(default) inverts the partial-likelihood information with the posterior-mean frailties andthetaPLUGGED IN as if known – it prices in none of their estimation uncertainty and understates: measured against the true sampling SD at theta = 1, se/SD was 0.79-0.88 and Wald-95 coverage 0.87-0.91 (clean at theta = 0)."jackknife"deletes one GROUP at a time and refits, pricing in frailty and theta estimation; it is honest but costs G extra EM fits, and its own validity is asymptotic in the NUMBER OF GROUPS (a handful of groups gives a noisy SE from few leave-outs).x (ndarray)
time (ndarray)
event (ndarray)
groups (ndarray)
max_iter (int)
tol (float)
ties (str)
- Returns:
A
FrailtyCoxResult(se_methodrecords which SEs you got).- Return type:
FrailtyCoxResult