OrderedCategorical#
- class superglm.OrderedCategorical(
- values: dict[str, float] | None = None,
- order: list[str] | None = None,
- basis: _SplineBase | None = None,
- base: str = 'most_exposed',
- grouping: Any = None,
- specials: list[str] | None = None,
Bases:
objectOrdered categorical feature smoothed by a spline over its level values.
Designed for continuous variables that arrive pre-binned into ordered categories (e.g. age bands, mileage bands). Maps category labels to numeric values and fits a smooth function through them, borrowing strength between adjacent levels. With
fit_reml(), REML selects the smoothing parameter automatically — the effective degrees of freedom will typically be much less than the number of levels.The smooth is configured by passing a
Spline()specification asbasis:OrderedCategorical( order=["low", "medium", "high"], basis=Spline(kind="ps", k=6), )
- Parameters:
- valuesdict[str, float] or None
Explicit mapping from category labels to numeric values (e.g. midpoints:
{"18-25": 21.5, "26-35": 30.5, ...}). Mutually exclusive withorder.- orderlist[str] or None
Ordered list of category labels. Numeric values are generated as
linspace(0, 1, len(order)). Mutually exclusive withvalues.- basisSpline, Piecewise, Polynomial object, or None
The shape fitted over the ordered levels. Deep-copied at construction, so mutating the passed object afterwards changes nothing here.
Spline(...)gives the penalized smooth:OrderedCategorical(order=[...], basis=Spline(kind="cr", k=6))
Omitting
basisretains the historical default P-spline,Spline(kind="ps", n_knots=5, degree=3, penalty="ssp", select=False). In either formn_knotsis clamped ton_levels - 1with a warning.Spline(knots=[...])may state knots as BAND NAMES (knots=["Mi060", "Mi066"]): each name resolves to that level’s VALUE on the smooth’s axis at construction – smooth-at-stated-breaks needs no new device, because a spline IS the C1 piecewise polynomial. Numeric entries stay axis values, so both spellings live on one scale.Piecewise(breaks=[...])gives stated kinks with NO smoothing penalty – an unpenalized main block, exactly like thespecials=block. The inner basis evaluates on level positions0..L-1(declared order;values=still sets the order but not the spacing). Breaks are stated as band names, with integer positions as the escape hatch;degrees=[...]states one polynomial degree per segment (0= flat/grouped tail), value-continuous at every seam by construction. Rating-table export stays one row per band at any degree, which is why per-segment degrees are legal here and only here.Piecewise’sextrapolationparameter is inert on the level axis – every level lies inside[0, L-1]by construction, so no policy ever binds – and is deliberately ignored rather than refused.Polynomial(powers=[...])gives classical orthogonal ordinal contrasts (thecontr.polydevice) built on the level positions and orthonormalized against the training exposure – SASORPOL’s weighted construction inside a modeling term. Classical trend practice keeps lower-order contrasts under a significant higher-order one (the hierarchical convention);powers=deliberately allows non-contiguous subsets, each orthogonal component individually in or out. Each stated power reports its own clean-z summary row – a main-effect property the segmentedPiecewisedeliberately does not claim.The legacy strings
"spline"and"step", and the scalar shortcut parameterskind,n_knots,degree,selectandpenalty, were removed in 0.24.0.- basestr
Reporting reference level.
"most_exposed"(default),"first", or a specific level name. This changes only the reported relativities and reference-adjusted intercept, not the fitted smooth.- specialslist[str] or None
Level labels held out of the smooth and fitted as free, unpenalized level effects — one indicator column and one coefficient each. Use for levels that are structurally different rather than merely sparse (a
MISSINGband, a structural zero); the penalty already handles sparse bands better than free levels do. A label listed here is removed fromorder/valuesif also present there, and never receives a numeric position on the smooth’s axis.
Examples
Using ordered level names (auto-spaced 0 to 1) with an explicit smooth:
OrderedCategorical( order=["18-25", "26-35", "36-45", "46-55", "56+"], basis=Spline(kind="ps", k=6), )
Using explicit midpoints:
OrderedCategorical( values={"18-25": 21.5, "26-35": 30.5, "36-45": 40.5}, basis=Spline(kind="cr", k=4), )
Independent, unsmoothed level effects should use
Categorical:Categorical(base="most_exposed")
- property constraint_kind: str | None#
Shape token declared on the inner basis (
"increasing", …).The constraint binds on the WHOLE LEVEL AXIS, not only on the
Lfitted level values – a stated contract, and deliberately conservative. Every published method for a monotone ordinal effect constrains the level effects directly (Rufibach, Comput. Statist. Data Anal. 54(6):1442-1456, 2010, Sec. 5; Barlow, Bartholomew, Bremner & Brunk, 1972); none constrains a curve between category positions, and the interval version is strictly stronger, since coefficient sign conditions are “sufficient but not necessary” for a monotone effect (Hofner, Kneib & Hothorn, Statist. Comput. 26:1-14, 2016, Sec. 3.3) and no proper linear-inequality basis exists for monotone CUBICS at all (Meyer, Ann. Appl. Statist. 2(3):1013-1033, 2008, Sec. 2). Seedocs/how-to/constrain-a-smooth.mdfor the measured cost.
- shape_axis(
- x: NDArray,
The inner basis’ numeric axis, and the rows that sit on it.
A shape constraint on an ordered term is stated over the inner spline’s level-score axis, not over the label column the frame carries. Engines that read a raw numeric column off the frame therefore cannot read this term’s; they have to resolve the axis through the wrapper, exactly as
transformdoes.The returned mask is not decoration: a
specials=level is fitted as a free effect with no coordinate on the smooth’s axis, so its rows are absent from the first return value and a caller carrying per-row weights must drop the same rows to keep them aligned.
- build( ) GroupInfo | list[GroupInfo]#
Build design columns from ordered categorical data.
With
specials=, returns two GroupInfos in a fixed order: the penalized spline block first, the unpenalized special-indicator block second. Downstream metadata readers select bysubgroup_type, but the order is part of the contract —_split_betaandtransformboth assume it. The free block covers the specials that have effective rows in THIS fit; when every declared special is pinned there is no second block and one GroupInfo comes back.
- transform(
- x: NDArray,
Build design matrix for new data using learned parameters.