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 the data
lung = gw.load_dataset("lung", backend="polars")

# Fit a Buckley-James model
bj = gw.BuckleyJames().fit("Surv(time, status) ~ age + sex", data=lung)
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=None,
    *,
    data=None,
)

Parameters

surv: Surv | Outcome | str

A right-censored Surv response, built with gw.Surv(time=..., event=...). An Outcome or a formula string such as 'Surv(time, status == 2) ~ age + sex' is also accepted, with its columns read from data. The right-hand side sets covariates.

covariates: Any = None

A dataframe (pandas or polars), a 2-D array, or a formula string (e.g., "age + sex") evaluated against the data argument. A list of column names in data also works.

data: Any = None
A data frame (pandas, Polars, PyArrow, DuckDB, a lazy frame, …) holding the columns named by the response and covariates. When surv is an Outcome or a formula, rows with a missing value in any column used are dropped before fitting. Covariate formula strings and lists of column names are also resolved here.

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")

bj = gw.BuckleyJames().fit("Surv(time, status) ~ age + sex", data=lung)
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). A data frame may also hold other columns. The covariates are picked out by name and coded as they were at fit time, so the frame the model was fit on can be passed as is.

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")
bj = gw.BuckleyJames().fit("Surv(time, status) ~ age + sex", data=lung)

bj.predict(lung[: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")
bj = gw.BuckleyJames(n_boot=200, seed=0).fit("Surv(time, status) ~ age + sex", data=lung)
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