Source code for experiencestudies.banding
"""Banded experience summaries.
Assign rows to size bands (the :func:`~actuarialpy.assign_band` primitive lives
in ``actuarialpy``) and then summarize experience within each band. Band edges
are always a parameter, since different analyses use different cut points.
"""
from __future__ import annotations
from collections.abc import Iterable, Sequence
import pandas as pd
from actuarialpy.banding import assign_band
from experiencestudies.experience import summarize_experience
[docs]
def summarize_by_band(
df: pd.DataFrame,
value_col: str,
bands: Sequence[float],
*,
labels: Sequence[str] | None = None,
expense_cols: str | Iterable[str],
revenue_cols: str | Iterable[str],
exposure_cols: str | Iterable[str] | None = None,
band_col: str = "band",
ratio_col: str | None = None,
right: bool = False,
profile: str | None = None,
) -> pd.DataFrame:
"""Assign size bands then summarize experience grouped by band.
Returns one row per band in band order (empty bands included), with the same
aggregates, loss ratio, and per-exposure metrics as
:func:`~experiencestudies.summarize_experience`.
"""
banded = assign_band(
df,
value_col,
bands,
labels=labels,
band_col=band_col,
right=right,
copy=True,
)
summary = summarize_experience(
banded,
groupby=band_col,
expense_cols=expense_cols,
revenue_cols=revenue_cols,
exposure_cols=exposure_cols,
ratio_col=ratio_col,
profile=profile,
)
# Preserve band order and surface empty bands explicitly.
order = list(banded[band_col].cat.categories)
summary[band_col] = pd.Categorical(summary[band_col], categories=order, ordered=True)
return summary.sort_values(band_col).reset_index(drop=True)