fit¶
The primary entry point for fitting linear mixed models with crossed random effects.
Accepts both random intercepts (via groups) and random slopes (via random).
Works with any narwhals-compatible DataFrame (pandas, polars, etc.).
- fit(formula, data, groups=None, method='REML', random=None, optimizer='lbfgsb', theta0=None, weights=None, offset=None, correlation=None, df_method='satterthwaite')[source]¶
Fit a linear mixed model with crossed random effects via profiled REML.
- Parameters:
formula – Patsy-syntax fixed-effects formula, e.g.
"y ~ x1 + x2".data – DataFrame containing all variables. Any narwhals-compatible frame (pandas, polars, …) is accepted.
groups – Column name (str) or list of column names for crossed random intercepts. Shorthand for
random=["(1|g1)", "(1|g2)", ...]. The first entry is the primary grouping factor.random – List of lme4-style random effect specifications, e.g.
["(1 + x | g1)", "(1 | g2)"]. Supports correlated (|) and independent (||) parameterisations. Takes precedence over groups when both are provided.method – Estimation method.
"REML"(default) maximises the restricted likelihood and is recommended for variance-component estimation."ML"maximises the full likelihood and is required for likelihood-ratio tests (LRT) comparing models with different fixed effects viainterlace.anova().optimizer – Optimizer for the REML criterion.
"lbfgsb"(default) usesscipy.optimize.minimizewith L-BFGS-B."bobyqa"usespybobyqa(requires thebobyqaoptional extra), a gradient-free trust-region method that is more robust near variance-parameter boundaries and matches lme4’s default.theta0 – Initial theta for the optimizer. Defaults to
np.ones(n_theta). Pass thethetaattribute of a previously fitted model to warm-start the optimizer (e.g. for case-deletion refits).weights – Observation-level prior weights, shape
(n,). Each observation’s contribution to the log-likelihood is scaled by its weight. Equivalent to pre-multiplying all data bysqrt(diag(weights)). Defaults to ones (unweighted).offset – Offset vector, shape
(n,). A known term added to the linear predictor that is not estimated. For LMMs (identity link) this is equivalent to fittingy - offset ~ …. Defaults to zero.
- Return type:
- Returns:
CrossedLMEResult – Drop-in replacement for statsmodels
MixedLMResults.- Parameters:
formula (str)
data (Any)
groups (str | list[str] | None)
method (str)
random (list[str] | None)
optimizer (str)
theta0 (ndarray | None)
weights (ndarray | None)
offset (ndarray | None)
correlation (Any | None)
df_method (str)
Examples
>>> import interlace >>> import pandas as pd >>> df = pd.DataFrame({ ... "y": [1.0, 2.0, 3.0, 1.5, 2.5, 3.5], ... "x": [0.1, 0.2, 0.3, 0.1, 0.2, 0.3], ... "g": ["a", "a", "a", "b", "b", "b"], ... }) >>> result = interlace.fit("y ~ x", df, groups="g") >>> result.fe_params Intercept ... x ... dtype: float64
Key parameters¶
Parameter |
Type |
Description |
|---|---|---|
|
|
Fixed-effects formula in Wilkinson notation (e.g. |
|
|
Input data |
|
|
Column name(s) for crossed random intercepts (shorthand) |
|
|
lme4-style random-effect specs, e.g. |
|
|
Estimator. Use |
|
|
Optimizer. |
|
|
Observation-level prior weights, shape (n,) |
|
|
Known term added to the linear predictor (not estimated) |
|
|
Residual correlation structure for longitudinal data |
|
|
|
|
|
Initial variance parameters; defaults to ones |
Examples¶
Random intercepts (shorthand)¶
import interlace
result = interlace.fit(
"rt ~ condition",
data=df,
groups=["subject", "item"], # crossed random intercepts
)
print(result.fe_params) # fixed-effect coefficients
print(result.variance_components) # σ² per grouping factor
print(result.aic, result.bic)
Random slopes¶
result = interlace.fit(
"rt ~ condition",
data=df,
random=[
"(1 + condition | subject)", # correlated intercept + slope
"(1 | item)", # intercept only
],
)
# random_effects["subject"] is a DataFrame: one column per term
print(result.random_effects["subject"])
print(result.varcov) # full random-effect covariance matrix
Model comparison with ML¶
# Fit with ML for likelihood ratio test
m1 = interlace.fit("y ~ x", data=df, groups="g", method="ML")
m2 = interlace.fit("y ~ x + z", data=df, groups="g", method="ML")
import scipy.stats
lrt_stat = 2 * (m2.llf - m1.llf)
p_value = scipy.stats.chi2.sf(lrt_stat, df=1)
See also¶
CrossedLMEResult — attributes on the returned
CrossedLMEResultPrediction — generating predictions from a fitted model
Correlation structures — AR(1) and compound symmetry for longitudinal data
Kenward-Roger degrees of freedom — Kenward-Roger denominator degrees of freedom
glmer — generalised linear mixed models (non-normal outcomes)
clmm — ordinal regression with random effects
coxme — Cox frailty models
Random Slopes Guide — when and how to use
random=Model Comparison Guide — LRT workflow with
method="ML"