# BuckleyJames


Buckley-James rank-based accelerated failure time regression.


Usage

``` python
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](AFT.md#greenwood.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_](KaplanMeier.md#greenwood.KaplanMeier.conf_low_), and [conf_high_](KaplanMeier.md#greenwood.KaplanMeier.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_](KaplanMeier.md#greenwood.KaplanMeier.conf_low_), [conf_high_](KaplanMeier.md#greenwood.KaplanMeier.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](Surv.md#greenwood.Surv) response and a covariate design (a 2-D array, a dataframe, or a formula string with `data`). An intercept is added automatically.


## Examples


``` python
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) | Fit the Buckley-James model to survival data. |
| [predict()](#predict) | Predict the linear predictor or survival probabilities from the fitted model. |
| [to_frame()](#to_frame) | Return the coefficient table as a DataFrame. |

------------------------------------------------------------------------


### fit()


Fit the Buckley-James model to survival data.


Usage

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


#### Parameters


`surv: Surv`  
A right-censored [Surv](Surv.md#greenwood.Surv) response. Built with [Surv.right()](Surv.md#greenwood.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


``` python
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

``` python
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](AFT.md#greenwood.AFT)'s or [RoystonParmar](RoystonParmar.md#greenwood.RoystonParmar)'s predictions.


#### Examples


``` python
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)

| time  | subject_1 | subject_2 |
|-------|-----------|-----------|
| f64   | f64       | f64       |
| 180.0 | 0.540495  | 0.604915  |
| 365.0 | 0.240099  | 0.278609  |
| 730.0 | 0.026538  | 0.059712  |


------------------------------------------------------------------------


### to_frame()


Return the coefficient table as a DataFrame.


Usage

``` python
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


``` python
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)

| term          | estimate  | std_error | statistic | p_value    | conf_low  | conf_high |
|---------------|-----------|-----------|-----------|------------|-----------|-----------|
| str           | f64       | f64       | f64       | f64        | f64       | f64       |
| "(Intercept)" | 6.379093  | 0.562108  | 11.348514 | 7.5433e-30 | 5.277381  | 7.480805  |
| "age"         | -0.023064 | 0.009091  | -2.537153 | 0.011176   | -0.040881 | -0.005247 |
| "sex"         | 0.491199  | 0.150234  | 3.269557  | 0.001077   | 0.196746  | 0.785653  |
