BuckleyJames

Buckley-James rank-based accelerated failure time regression.

Usage

Source

BuckleyJames(
    *,
    max_iter=200,
    tol=1e-06,
    n_boot=None,
    seed=None,
    conf_level=0.95,
)

Fits \log(T) = X\beta + \varepsilon without assuming a distribution for \varepsilon, by alternating Kaplan-Meier-based imputation of censored log-times with ordinary least squares refitting until \beta stabilizes. This is a semiparametric alternative to AFT: it avoids committing to a parametric error distribution, at the cost of an iterative fit, occasional slow or oscillating convergence, and no closed-form standard errors (available here only via optional bootstrap resampling, n_boot=).

When there is no censoring at all, every residual is exact and the algorithm converges in a single step to the ordinary least squares fit of \log(T) on X.

Parameters

max_iter: int = 200

Maximum number of Buckley-James iterations (default 200).

tol: float = 1e-06

Convergence tolerance on the largest change in any coefficient between iterations (default 1e-6).

n_boot: int | None = None

Number of bootstrap resamples for standard errors and confidence intervals. If None (the default), std_error_, conf_low_, and conf_high_ are nan (Buckley-James has no closed-form variance).

seed: int | None = None

Random seed for bootstrap resampling (ignored if n_boot is None).

conf_level: float = 0.95
Confidence level for bootstrap coefficient intervals (default 0.95).

Returns

Fitted estimator
Call fit() to produce a fitted estimator with cached results (coef_, std_error_, z_, p_value_, conf_low_, conf_high_, n_iter_, converged_, loglik_-free since there is no likelihood), accessible as arrays or exported to DataFrames.

Details

Call fit(surv, covariates) with a right-censored Surv response and a covariate design (a 2-D array, a dataframe, or a formula string with data). An intercept is added automatically.

Examples

import greenwood as gw

# Load data and build a right-censored response
lung = gw.load_dataset("lung", backend="polars")
y = gw.Surv.right(lung["time"], event=(lung["status"] == 2))

# Fit a Buckley-James model
bj = gw.BuckleyJames().fit(y, lung[["age", "sex"]])
bj
BuckleyJames (rank-based accelerated failure time regression)

                 coef  se(coef)   z   p
(Intercept)     6.379        NA  NA  NA
age          -0.02306        NA  NA  NA
sex            0.4912        NA  NA  NA

n = 228, events = 165
iterations = 13, converged = True

Methods

Name Description
fit() Fit the Buckley-James model to survival data.
predict() Predict the linear predictor or survival probabilities from the fitted model.
to_frame() Return the coefficient table as a DataFrame.

fit()

Fit the Buckley-James model to survival data.

Usage

Source

fit(
    surv,
    covariates,
    *,
    data=None,
)

Parameters

surv: Surv

A right-censored Surv response. Built with Surv.right().

covariates: Any

A dataframe (pandas or polars), a 2-D array, or a formula string (e.g., "age + sex") evaluated against the data argument.

data: Any = None
A dataframe to evaluate the formula string (ignored if covariates is a dataframe or array).

Returns

BuckleyJames
The fitted estimator itself (for method chaining) with cached coefficient arrays (coef_, std_error_, z_, p_value_) and convergence diagnostics (n_iter_, converged_).

Examples

import greenwood as gw

lung = gw.load_dataset("lung", backend="polars")
y = gw.Surv.right(lung["time"], event=(lung["status"] == 2))

bj = gw.BuckleyJames().fit(y, lung[["age", "sex"]])
bj
BuckleyJames (rank-based accelerated failure time regression)

                 coef  se(coef)   z   p
(Intercept)     6.379        NA  NA  NA
age          -0.02306        NA  NA  NA
sex            0.4912        NA  NA  NA

n = 228, events = 165
iterations = 13, converged = True

predict()

Predict the linear predictor or survival probabilities from the fitted model.

Usage

Source

predict(
    newdata=None,
    *,
    type="survival",
    times=None,
    format=None,
)

Parameters

newdata: Any = None

Covariate values for prediction. A DataFrame (Pandas or Polars), 2-D array, or None (the default, uses the training data).

type: str = "survival"

"survival" (default): survival probabilities S(t \mid x) at times, evaluated by shifting the fitted residual Kaplan-Meier curve by each subject’s linear predictor. "lp": the linear predictor X\beta (log-time location) only; returns an array.

times: Any = None

Query times for type="survival" (ignored for "lp"). Required for "survival".

format: str | None = None
Output format for type="survival": None (auto-detect), "pandas", "polars", or "pyarrow". Ignored for type="lp" (which always returns an array).

Returns

ndarray or DataFrame
An array of shape (n_subjects,) for type="lp". A DataFrame with a time column and one column per subject for type="survival".

Details

Because Buckley-James makes no distributional assumption, survival predictions reuse the empirical Kaplan-Meier curve of the fitted residuals rather than a closed-form survival function: S(t \mid x) = \hat{S}_{\text{resid}}(\log t - x^\top\hat\beta). This curve is only as reliable as the residual sample size and is not smooth like AFT’s or RoystonParmar’s predictions.

Examples

import greenwood as gw

lung = gw.load_dataset("lung", backend="polars")
y = gw.Surv.right(lung["time"], event=(lung["status"] == 2))
bj = gw.BuckleyJames().fit(y, lung[["age", "sex"]])

bj.predict(lung[["age", "sex"]][:2], type="survival", times=[180, 365, 730],
           format="polars")
shape: (3, 3)
timesubject_1subject_2
f64f64f64
180.00.5404950.604915
365.00.2400990.278609
730.00.0265380.059712

to_frame()

Return the coefficient table as a DataFrame.

Usage

Source

to_frame(
    *,
    format=None,
)

Exports one row per term, including the intercept. std_error, p_value, conf_low, and conf_high are nan unless the model was fit with n_boot=.

Parameters

format: str | None = None
Output format: None (default), "pandas", "polars", or "pyarrow".

Returns

pandas.DataFrame, polars.DataFrame, or pyarrow.Table
A tidy table with columns term, estimate, std_error, statistic, p_value, conf_low, and conf_high.

Examples

import greenwood as gw

lung = gw.load_dataset("lung", backend="polars")
y = gw.Surv.right(lung["time"], event=(lung["status"] == 2))
bj = gw.BuckleyJames(n_boot=200, seed=0).fit(y, lung[["age", "sex"]])
bj.to_frame(format="polars")
shape: (3, 7)
termestimatestd_errorstatisticp_valueconf_lowconf_high
strf64f64f64f64f64f64
"(Intercept)"6.3790930.56210811.3485147.5433e-305.2773817.480805
"age"-0.0230640.009091-2.5371530.011176-0.040881-0.005247
"sex"0.4911990.1502343.2695570.0010770.1967460.785653