# plot_weibull()


Plot Kaplan-Meier estimates on distribution-linearizing axes.


Usage

``` python
plot_weibull(
    km,
    *,
    aft=None,
    dist="weibull",
    title=None,
    xlab=None,
    ylab=None,
    width=500,
    height=300,
)
```


Produces a diagnostic scatter plot of Kaplan-Meier survival estimates on transformed axes where data from the specified parametric distribution falls on a straight line. This is the classic "Weibull plot" (complementary log-log transform) generalized to other AFT distributions.

For stratified Kaplan-Meier fits, each stratum is drawn as a separate colored series. Parallel lines indicate the proportional hazards assumption holds between groups.

An optional fitted [AFT](AFT.md#greenwood.AFT) model overlays the theoretical parametric line on the empirical points, showing goodness-of-fit visually. The overlay is available only for unstratified Kaplan-Meier fits.


## Parameters


`km: KaplanMeier`  
A fitted [KaplanMeier](KaplanMeier.md#greenwood.KaplanMeier) object (stratified or unstratified).

`aft: Any | None = None`  
An optional fitted [AFT](AFT.md#greenwood.AFT) model for a parametric overlay line. Only allowed with an unstratified `km`. The AFT's distribution must match the `dist` parameter (with `"exponential"` accepted when `dist="weibull"`).

`dist: str = ``"weibull"`  
Distribution whose linearizing transform is applied: `"weibull"` (default), `"lognormal"`, or `"loglogistic"`.

`title: str | None = None`  
Chart title. Defaults to `None` (no title).

`xlab: str | None = None`  
X-axis label. Defaults to `"log(time)"`.

`ylab: str | None = None`  
Y-axis label. Defaults to a distribution-specific label.

`width: int = ``500`  
Chart dimensions in pixels (defaults 500 x 300).

`height: int = ``500`  
Chart dimensions in pixels (defaults 500 x 300).


## Returns


`altair.LayerChart`  
An interactive Altair chart.


## Examples

Check the Weibull assumption for lung cancer survival by sex:


``` python
import greenwood as gw

lung = gw.load_dataset("lung", backend="polars")
death = gw.Outcome.surv(time="time", event="status")

# Stratified KM where parallel lines suggest PH holds
km = gw.KaplanMeier().fit(death, by="sex", data=lung)
gw.plot_weibull(km)
```


<style>
  #altair-viz-ed0cdb0b3aa6469796c58d51669506fc.vega-embed {
    width: 100%;
    display: flex;
  }

  #altair-viz-ed0cdb0b3aa6469796c58d51669506fc.vega-embed details,
  #altair-viz-ed0cdb0b3aa6469796c58d51669506fc.vega-embed details summary {
    position: relative;
  }
</style>


Overlay a fitted Weibull AFT on an unstratified KM:


``` python
km_overall = gw.KaplanMeier().fit(death, data=lung)
aft = gw.AFT(dist="weibull").fit("Surv(time, status) ~ age + sex", data=lung)
gw.plot_weibull(km_overall, aft=aft)
```


<style>
  #altair-viz-af74e0968a3a40c9823952d8c6bf087e.vega-embed {
    width: 100%;
    display: flex;
  }

  #altair-viz-af74e0968a3a40c9823952d8c6bf087e.vega-embed details,
  #altair-viz-af74e0968a3a40c9823952d8c6bf087e.vega-embed details summary {
    position: relative;
  }
</style>
