Smooth non-linear hazard ratio curve for a continuous covariate.
SmoothHRResult(
term,
reference,
grid,
log_hr,
hr,
log_hr_lower,
log_hr_upper,
hr_lower,
hr_upper,
df,
knots,
adjustment,
)
Contains the estimated log-hazard ratio (and hazard ratio) as a function of a continuous covariate, computed by refitting the Cox model with a B-spline basis expansion. The curve shows how the covariate’s effect on the hazard varies across its range, relative to a reference value.
Attributes
term: str
-
Name of the covariate whose smooth effect is estimated.
reference: float
-
Reference value of the covariate. The log-HR is zero at this point.
grid: Array
-
Array of covariate values at which the curve is evaluated.
log_hr: Array
-
Log hazard ratio at each grid point (relative to reference).
hr: Array
-
Hazard ratio at each grid point (exp(log_hr)).
log_hr_lower: Array
-
Lower confidence bound on the log-HR.
log_hr_upper: Array
-
Upper confidence bound on the log-HR.
hr_lower: Array
-
Lower confidence bound on the HR (exp(log_hr_lower)).
hr_upper: Array
-
Upper confidence bound on the HR (exp(log_hr_upper)).
df: int
-
Degrees of freedom of the spline (number of basis functions).
knots: Array
-
Interior knot positions used for the B-spline basis.
adjustment: dict[str, float]
-
Dictionary of covariate names and the values they were held at.
Examples
Estimate a smooth hazard ratio curve for age from a Cox model fit on the lung dataset. The curve shows how the hazard changes across the range of age, relative to the median:
import greenwood as gw
lung = gw.load_dataset("lung", backend="polars")
cox = gw.CoxPH().fit("Surv(time, status) ~ age + sex", data=lung)
shr = cox.smooth_hr(term="age")
shr
SmoothHRResult(term='age', reference=62.44736842105263, df=4, grid=200 points)
Convert the curve to a DataFrame on the hazard-ratio scale:
shr.to_frame(scale="hr", format="polars")
shape: (200, 4)| age | hr | hr_lower | hr_upper |
|---|
| f64 | f64 | f64 | f64 |
| 39.0 | 0.286315 | 0.045322 | 1.808755 |
| 39.21608 | 0.301367 | 0.051335 | 1.769193 |
| 39.432161 | 0.316818 | 0.058171 | 1.725496 |
| 39.648241 | 0.332654 | 0.065374 | 1.692704 |
| 39.864322 | 0.348859 | 0.073246 | 1.661556 |
| … | … | … | … |
| 81.135678 | 2.639734 | 0.839804 | 8.297414 |
| 81.351759 | 2.701119 | 0.809741 | 9.010339 |
| 81.567839 | 2.764617 | 0.781298 | 9.782569 |
| 81.78392 | 2.830307 | 0.751264 | 10.662885 |
| 82.0 | 2.898273 | 0.721253 | 11.646384 |
Methods
|
Name
|
Description
|
|
to_frame()
|
Return the smooth curve as a DataFrame.
|
to_frame()
Return the smooth curve as a DataFrame.
to_frame(
*,
scale="log_hr",
format=None,
)
Parameters
scale: str = "log_hr"
-
"log_hr" (the default) returns log hazard ratios and confidence bounds. "hr" returns hazard ratios (exponentiated).
format: str | None = None
-
Output format:
None (default), "pandas", "polars", or "pyarrow".
Returns
pandas.DataFrame, polars.DataFrame, or pyarrow.Table
-
Examples
Export the smooth hazard ratio curve on the log-HR scale (the default):
import greenwood as gw
lung = gw.load_dataset("lung", backend="polars")
cox = gw.CoxPH().fit("Surv(time, status) ~ age + sex", data=lung)
shr = cox.smooth_hr(term="age")
shr.to_frame(format="polars")
shape: (200, 4)| age | log_hr | log_hr_lower | log_hr_upper |
|---|
| f64 | f64 | f64 | f64 |
| 39.0 | -1.250662 | -3.093962 | 0.592639 |
| 39.21608 | -1.199427 | -2.969377 | 0.570524 |
| 39.432161 | -1.149428 | -2.844371 | 0.545514 |
| 39.648241 | -1.100653 | -2.727634 | 0.526327 |
| 39.864322 | -1.053087 | -2.613929 | 0.507754 |
| … | … | … | … |
| 81.135678 | 0.970678 | -0.174587 | 2.115944 |
| 81.351759 | 0.993666 | -0.21104 | 2.198373 |
| 81.567839 | 1.016902 | -0.246798 | 2.280602 |
| 81.78392 | 1.040385 | -0.285998 | 2.366769 |
| 82.0 | 1.064115 | -0.326765 | 2.454996 |
Switch to the exponentiated hazard-ratio scale:
shr.to_frame(scale="hr", format="polars")
shape: (200, 4)| age | hr | hr_lower | hr_upper |
|---|
| f64 | f64 | f64 | f64 |
| 39.0 | 0.286315 | 0.045322 | 1.808755 |
| 39.21608 | 0.301367 | 0.051335 | 1.769193 |
| 39.432161 | 0.316818 | 0.058171 | 1.725496 |
| 39.648241 | 0.332654 | 0.065374 | 1.692704 |
| 39.864322 | 0.348859 | 0.073246 | 1.661556 |
| … | … | … | … |
| 81.135678 | 2.639734 | 0.839804 | 8.297414 |
| 81.351759 | 2.701119 | 0.809741 | 9.010339 |
| 81.567839 | 2.764617 | 0.781298 | 9.782569 |
| 81.78392 | 2.830307 | 0.751264 | 10.662885 |
| 82.0 | 2.898273 | 0.721253 | 11.646384 |