Random effect basis (one-hot encoding with identity penalty).
A random effect basis represents a grouping factor — subject ID, site, batch, cluster — as a penalized random intercept rather than as a fixed factor with one unconstrained parameter per level. It is equivalent to mgcv’s bs="re" basis and to the random-intercept term of a linear mixed model: each unique level of the grouping variable gets its own one-hot column, and an identity penalty shrinks the estimated level effects toward their common mean, with the amount of shrinkage controlled by a single smoothing parameter selected by GCV or REML (equivalent to the group-level variance in a mixed model). Choose this basis over an ordinary fixed factor whenever the number of levels is large, levels have unbalanced sample sizes, or the goal is to borrow strength across levels rather than to estimate every level’s effect independently; choose it over MRFBasis or FactorSmoothBasis when the grouping levels have no spatial/ordering structure to exploit and only an exchangeable random intercept is wanted.
The covariate should be a 1-D array of group labels (strings, integers, or any hashable type).
Parameters
k: int = -1
-
Maximum number of levels to retain. If
-1 (the default), all observed levels are kept as basis functions. If a positive integer smaller than the number of observed levels, only the first k (in sorted level order) are used and any other levels are silently dropped from the basis (their rows become all-zero); this is rarely desirable for a random effect, so the default of -1 should normally be left as-is unless there is a specific reason to cap the number of levels.
Notes
Let there be k unique levels of the grouping factor after fit(). The basis matrix B is the n x k matrix of level indicators, B[i, j] = 1 if observation i belongs to level j and 0 otherwise. The penalty matrix is the k x k identity,
\mathbf{S} = \mathbf{I}_k,
so the roughness penalty is simply the sum of squared level effects,
\boldsymbol{\beta}^\top \mathbf{S} \boldsymbol{\beta} = \sum_{j=1}^{k} \beta_j^2 ,
exactly the ridge-type penalty that shrinks every group deviation toward zero as lambda grows, with no level treated differently from any other. Because the identity matrix is full rank, null_space_dimension() is always 0 — there is no unpenalized subspace, and in principle the entire random effect can be shrunk away as lambda \to \infty, recovering a model with no group-level variation at all. Because the raw indicator columns are collinear with an overall intercept (every row sums to 1), identifiability_constraints() returns a sum-to-zero constraint that should be enforced when the random effect is fit alongside a fixed intercept term. fit() raises ValueError if fewer than two unique levels are present, since a random effect with a single level carries no information about between-group variation.
Examples
import numpy as np
from whittaker.smooths.random import RandomEffectBasis
rng = np.random.default_rng(0)
groups = rng.choice(["a", "b", "c", "d"], size=50)
basis = RandomEffectBasis().fit(groups)
B = basis.basis_matrix(groups)
S = basis.penalty_matrix()
B.shape, S.shape
Attributes
|
Name
|
Description
|
|
k
|
Requested or actual number of group levels.
|
|
levels
|
Sorted array of unique group labels retained during fit().
|
|
n_basis
|
Number of basis functions, i.e. the number of retained group levels.
|
k
Requested or actual number of group levels.
Before fit() is called, returns the k value passed at construction (the requested cap on the number of levels, or -1 for “all levels”). After fit(), returns the actual number of group levels retained.
levels
Sorted array of unique group labels retained during fit().
n_basis
Number of basis functions, i.e. the number of retained group levels.
Raises
RuntimeError
-
If accessed before
fit() has been called.
Methods
basis_matrix()
Evaluate the one-hot random effect basis at x.
Parameters
x: NDArray
-
Grouping variable values. Shape
(n,). Values not seen during fit() produce an all-zero row (no level indicator is set).
Returns
NDArray
-
Design matrix of shape
(n, k) where k is the number of levels retained during fit(). Each row has at most one entry equal to 1.0.
fit()
Fit the random effect basis to training data.
Determines the set of unique group levels present in x; these define the columns of the basis matrix produced by basis_matrix().
Parameters
x: NDArray
-
Training grouping variable. Shape
(n,), of any hashable dtype (strings, integers, etc.).
Returns
RandomEffectBasis
-
Returns
self for method chaining.
Raises
ValueError
-
If fewer than 2 unique levels are present in
x, or if k is requested but is less than 2.
identifiability_constraints()
Return the sum-to-zero constraint row for the intercept.
identifiability_constraints()
Returns
NDArray
-
A
(1, k) matrix of equal weights 1 / k whose product with the coefficient vector forces the mean fitted level effect to be zero, resolving the confound between the random effect’s implicit constant and a fixed model intercept.
null_space_dimension()
Return 0: the identity penalty has no unpenalized subspace.
Because the penalty matrix is the full-rank identity I_k, every basis coefficient is penalized and there is no unpenalized null space, unlike smooths with derivative-based penalties (e.g. TPRS) that leave polynomial trends unpenalized.
penalty_matrix()
Return the (k, k) identity penalty matrix.
Returns
NDArray
-
The
k x k identity matrix, where k is the number of retained levels. Every coefficient is penalized equally.