Demonstration
BART-Survival supports both an intuitive high-level API (SurvBART) for rapid, boilerplate-free modeling and a granular low-level API for custom pooled person-time workflows.
1. High-Level API (SurvBART)
In this workflow, tabular covariates and time-to-event outcomes are passed directly to SurvBART. Discretization, pooled person-time data expansion, out-of-sample grid formatting, and posterior survival curve derivation are handled automatically.
import numpy as np
import pandas as pd
from bart_survival import SurvBART, simulate_confounded_survival_data
# Generate a synthetic observational clinical cohort with known treatment effect
df, meta = simulate_confounded_survival_data(
N=300,
treatment_hr=1.8,
censoring_rate=0.2,
seed=42
)
features = ["inpatient", "age", "stage", "los"]
X = df[features]
# 1. Initialize SurvBART using the recommended standard scientific preset
# (50 trees, 1000 draws, 250 tune, 4 chains, thin=4, 512 empirical cutpoints)
model = SurvBART.preset_standard()
# 2. Fit directly from tabular covariates and survival outcomes
model.fit_survival(
X=X,
time=df["time"],
status=df["status"],
time_scale=5.0, # 5-day intervals
progressbar=True,
random_seed=42
)
# 3. Predict cumulative survival curves S(t) with 95% Credible Intervals
surv_summary = model.predict_survival(X, return_quantiles=True)
print("Survival curve shape:", surv_summary["mean"].shape)
print("Mean S(t):", surv_summary["mean"].mean(axis=0))
# 4. Normalized variable inclusion proportions (Feature Importance)
print("\nPosterior Feature Importance:")
print(model.feature_importance())
# 5. Causal Treatment Effect with Conditional Support Audit
# Detects positivity violations (e.g., zero LOS among outpatients)
effect = model.estimate_effect(
X=X,
primary_col="inpatient",
values=[0, 1]
)
print("\nEstimated Hazard Ratio Curve:", effect["hazard_ratio_mean"])
print("Flagged Support Violations:", effect["flagged_support_violations"])
2. Granular Step-by-Step API (TAD & PAD)
The low-level API provides full transparency into the pooled person-time Training Augmented Dataset (TAD) and Prediction Augmented Dataset (PAD). In this demonstration, the open Rossi recidivism benchmark dataset from lifelines is used [@rossi1980].
from lifelines.datasets import load_rossi
from bart_survival import (
SurvBART,
format_survival_data,
format_prediction_data,
compute_survival_curves
)
import numpy as np
# Load Rossi recidivism dataset
rossi = load_rossi()
time = rossi["week"].values
status = rossi["arrest"].values
X = rossi[["fin", "age", "race", "wexp", "mar", "paro", "prio"]].values
# 1. Transform into pooled person-time TAD dataset
# Time (originally in weeks) is scaled by 4 into monthly intervals
trn = format_survival_data(
y_time=time,
y_status=status,
x=X,
time_scale=4.0
)
# 2. Generate out-of-sample prediction PAD grid
post_test = format_prediction_data(
y_time=time,
y_status=status,
x=X,
time_scale=4.0
)
# 3. Initialize SurvBART with custom parameters
model = SurvBART(
trees=50,
draws=1000,
tune=500,
chains=4,
thin=5,
update_fraction=1.0,
split_method="empirical"
)
# 4. Fit model on TAD
model.fit(
y=trn["y"],
X=trn["x"],
weights=trn["w"],
coords=trn["coord"],
progressbar=True,
random_seed=5
)
# 5. Predict out-of-sample hazards and compute S(t)
post_preds = model.predict(post_test["post_x"], coords=post_test["coords"])
sv_prob = compute_survival_curves(post_preds, coords=post_test["coords"])
# S(t) has shape (n_draws, n_subjects, n_time_intervals)
print("S(t) shape:", sv_prob["sv"].shape)
# Population-level average survival curve S(t) across subjects and draws:
mean_survival = sv_prob["sv"].mean(axis=(0, 1))
print("Population Mean S(t):", mean_survival)