# linearmodels: panel, instrumental variable and system estimators that statsmodels leaves out

> linearmodels is a Python package by Kevin Sheppard that extends statsmodels with fixed and random effects panel models, IV estimators, GMM, factor asset pricing models and seemingly unrelated regression, all with formula support and clustered covariance options. The thing to check first is the dependency floor, which has a scheduled break for Python 3.10 and NumPy 1.x.

**bashtage/linearmodels** — Additional linear models including instrumental variable and panel data models that are missing from statsmodels.

- Repository: https://github.com/bashtage/linearmodels
- Website: https://bashtage.github.io/linearmodels/
- Stars: 1,077 · Forks: 206
- Language: Python
- License: NCSA
- Published: 2026-10-19 · Updated: 2026-10-19 · Language: en
- Canonical page: https://hysenlabs.com/projects/bashtage-linearmodels

## The gap linearmodels was written to fill

The package description is unusually honest about its purpose: additional linear models including instrumental variable and panel data models that are missing from statsmodels. The README frames it as linear regression models for Python that extend statsmodels.

Statsmodels is the reference point for the whole design. It is what the API imitates, what the formula interface resembles, and what the documentation assumes you already have installed. The dependency floor states statsmodels 0.14.6 or higher, and the pyproject.toml comment on that requirement says it is the first release that imports with pandas 3. So the relationship is dependency as well as inspiration, and a project already using statsmodels gets a familiar surface.

The scope divides into five families, all listed in the README. Panel models cover fixed effects with a maximum of two-way, random effects, first difference regression, the between estimator, pooled regression, Fama-MacBeth estimation, and two specification tests, the Hausman test of random effects against fixed effects and the Pesaran CD test of cross-sectional dependence. Instrumental variable estimators cover two stage least squares, limited information maximum likelihood, k-class estimators, generalized method of moments with a continuously updating variant, and Jackknife IV, with the Cragg-Donald and Kleibergen-Paap rank tests of the first stage. There is also a high-dimensional regression section for absorbing least squares, factor asset pricing models estimated in two or three steps, by time series or by GMM, and system regression covering SUR/SURE, three stage least squares and GMM system estimation.

The project is designed to work equally well with NumPy, Pandas or xarray data, and xarray is the one optional dependency in the runtime list.

The plan and status section is the part worth reading twice, because it tells you exactly what does not exist yet. Linear instrumental variable estimation, linear panel model estimation, Fama-MacBeth regression, linear factor asset pricing and system regression are all marked complete. Linear IV panel model estimation and dynamic panel model estimation are both marked not started. If your research design needs a dynamic panel estimator such as Arellano-Bond, this package will not provide it.

## PanelOLS with a MultiIndex, and the formula alternative

The panel example uses the classic Grunfeld regression, and it shows the indexing convention the package expects. A MultiIndex of entity and time is what defines the panel structure:

```python
import numpy as np
from statsmodels.datasets import grunfeld
data = grunfeld.load_pandas().data
data.year = data.year.astype(np.int64)
# MultiIndex, entity - time
data = data.set_index(['firm','year'])
from linearmodels import PanelOLS
mod = PanelOLS(data.invest, data[['value','capital']], entity_effects=True)
res = mod.fit(cov_type='clustered', cluster_entity=True)
```

Four things are worth noting. The data comes from statsmodels datasets, so the package expects a pandas DataFrame with a two level MultiIndex rather than a long form table with entity and time columns. The dependent variable is passed positionally and the regressors as a DataFrame subset, giving the estimator a statsmodels style signature. entity_effects=True is a constructor argument, not a fit argument, so the model specification is fixed when you build the object. And the fit call requests clustered covariance with cluster_entity=True, which clusters by entity rather than by entity and time, and that choice is one of the decisions that changes your standard errors.

The formula interface does the same job more compactly, and it is where the special effect keywords live:

```python
from linearmodels import PanelOLS
mod = PanelOLS.from_formula('invest ~ value + capital + EntityEffects', data)
res = mod.fit(cov_type='clustered', cluster_entity=True)
```

The README states the formula interface for PanelOLS supports the special values EntityEffects and TimeEffects, which add entity fixed and time effects respectively. A two way model is then both keywords in one formula.

One detail that affects compatibility with the rest of your Python stack: formula support comes from the formulaic package, which the README describes as a replacement for patsy. If your existing code base builds formulas with patsy, the two are not interchangeable objects, and mixing them in one project means two formula systems rather than one.

## IV2SLS marks endogenous regressors inside square brackets

The instrumental variable example is the one piece of the API that is genuinely unusual, and it is worth reading carefully before you write your own model strings:

```python
import numpy as np
from linearmodels.iv import IV2SLS
from linearmodels.datasets import mroz
data = mroz.load()
mod = IV2SLS.from_formula('np.log(wage) ~ 1 + exper + exper ** 2 + [educ ~ motheduc + fatheduc]', data)
```

The expressions in the square brackets indicate endogenous regressors, before the tilde, and the instruments, after it. So in the example educ is treated as endogenous and motheduc and fatheduc are used as its instruments, while exper and exper squared are exogenous. The tilde inside the bracket is the instrument list, which is a second tilde in the same formula string, and a formula parser that does not know this convention will not read it correctly.

The data comes from the mroz dataset bundled in linearmodels.datasets, so the package ships its own example data rather than relying only on statsmodels datasets.

The estimator families in the iv module follow the same idea. Two stage least squares is the baseline, limited information maximum likelihood is the alternative with the same identification structure, and k-class estimators sit between 2SLS and LIML by construction. Generalized method of moments is available both in its standard form and in a continuously updating variant, and Jackknife IV gives the JIVE estimator, which addresses the finite sample bias of 2SLS rather than the identification problem. For a diagnostic, the Cragg-Donald and Kleibergen-Paap rank tests assess the rank of the first stage, which is the underidentification question.

Absorbing least squares appears in the README as a separate high-dimensional regression item, and the examples directory contains a notebook named iv_absorbing-regression.ipynb. The package therefore does not limit itself to the classical estimators, and the examples folder is the fastest way to see how the newer ones are called.

## Installing from PyPI, and the dependency floor that keeps moving

The released package installs with pip:

```bash
pip install linearmodels
```

Binary wheels are available for Windows, macOS and Linux. Where a wheel is not available, pip builds from source, and that build requires a C compiler. That is worth knowing before you try to install into a minimal container image.

The main branch installs by cloning and building:

```bash
git clone https://github.com/bashtage/linearmodels
cd linearmodels
pip install .
```

The build uses meson-python, and pip installs the other build requirements, Cython, NumPy and setuptools_scm, automatically. For development the README asks you to install the requirements first and then build an editable install:

```bash
python -m pip install -r requirements.txt -r requirements-dev.txt
python -m pip install -e . --no-build-isolation
```

The --no-build-isolation flag matters. Without it, pip creates a fresh build environment, and the build environment installs numpy>=2.0.0,<3 while your runtime environment can keep numpy 1.23.5 or newer, so the two lists apply to different environments. The pyproject.toml even carries a comment on the Cython bound saying to keep it in sync with the Cython check in meson.build, which is the sort of note that only appears when a build has broken on a version drift.

That split is deliberate but confusing. The build requirements and the runtime requirements are different lists with different floors. The build needs a modern NumPy, the runtime accepts a 1.x NumPy, and pip will pick the newer one for the build while your installed environment keeps the older one.

The runtime requirements for the current release are Python 3.10 or newer, NumPy 1.23.5 or newer, SciPy 1.8 or newer, pandas 1.4 or newer, statsmodels 0.14.6 or newer, formulaic 1.2.1 or newer, pyhdfe 0.2.0 or newer, mypy_extensions 0.4 or newer, packaging, and optionally xarray 0.16 or newer. The README also states the plan going forward: linearmodels 7.1 is the last release that supports Python 3.10 and NumPy 1.x, meaning NumPy below 2, and later releases will raise the minimum supported versions of Python, NumPy and the other dependencies.

That is a scheduled break for anyone on an older stack, and it is stated plainly enough that you can plan around it rather than discover it in a dependency resolver error.

## The meson build, the version file and why the number is dynamic

The build system is meson, with meson-python as the backend. The repository listing shows meson.build and meson.options at the top level alongside pyproject.toml, and the pyproject.toml declares the build backend as mesonpy with a requires list of meson-python, cython>=3.1.0,<4, numpy>=2.0.0,<3 and setuptools_scm>=9.2.0,<10.

The version is the interesting part. The project section marks the version as dynamic, and a comment explains where it comes from: the version is set in meson.build, which runs linearmodels/_build/git_version.py. So the version is derived from git metadata through setuptools_scm rather than being written into pyproject.toml. The consequence for a consumer is that the source tree build needs the git history to produce a sensible version, and a tarball without git metadata may not install cleanly, which is a common reason to prefer the published wheel over a source build.

The pyproject.toml also shows the metadata that a maintainer would care about. The author is Kevin Sheppard. The classifiers list Development Status:: 5 - Production/Stable, and the intended audiences are End Users/Desktop, Financial and Insurance Industry, and Science/Research, with Python 3.10 through 3.15 listed. The pyproject keyword list covers linear models, regression, instrumental variables, IV, panel, fixed effects, clustered, heteroskedasticity, endogeneity, instruments, statistics, statistical inference and econometrics.

The licence identifier in pyproject.toml is NCSA, with LICENSE.md as the licence file and license-files pointing at it. The README does not restate the licence terms, so the text of LICENSE.md is the only authoritative statement of what you may do with the package, and you should read it before redistributing it inside a commercial product.

The repository also carries an azure-pipelines.yml, a ci/ directory, a.coveragerc, a.flake8 and a SECURITY.md, so testing, coverage, linting and a security contact are all part of the project rather than afterthoughts.

## Maintenance, release history and the documentation build

The repository is not archived, and the last push was on 2026-10-15, so the code is being worked on. The release history is v7.0 on 2025-10-21, v6.1 on 2024-09-24 and v6.0 on 2024-04-16. Those are substantial version numbers with roughly a year between some of them, and the README refers to a 7.1 release as the last one supporting Python 3.10 and NumPy 1.x, which means work has continued past the 7.0 tag without a matching entry in that short list.

Documentation is built in two flavours, and the distinction is a nice touch. The stable documentation is built by GitHub Actions when a release is published, and the development documentation is built by the same workflow on every push to main. The workflow file is generate-documentation.yml in the .github/workflows directory. The consequence is that the development docs are always newer than the released docs, so if you are reading the development build while running a released version, you may be reading behaviour that has not shipped.

The examples directory is the other documentation surface, and it is unusually complete. It holds notebooks for panel examples, panel data formats, panel using formulas, IV basic, advanced and formula examples, an absorbing regression notebook, asset pricing examples in both direct and formula variants, system examples, system formulas, and a three stage least squares notebook, alongside three PNG files of a system regression result table. The presence of a system_correct-greene-table reference image suggests the system estimators are checked against published textbook output, which is a good sign for a package whose whole value is getting the algebra right.

One thing the README does not discuss is a deprecation policy or a migration guide for the major version bumps, so if you are moving from 6.x to 7.x you will need to read the changelog rather than a written upgrade path.

## Conclusion

linearmodels fits an econometrics team working in Python who needs panel fixed effects, two stage least squares, GMM or seemingly unrelated regression with a statsmodels style API and formula interface. It is the wrong tool if you need dynamic panel estimators or a combined IV panel model, because the project marks both as not started, and it is awkward if your environment pins NumPy 1.x, because the package is dropping Python 3.10 and NumPy 1.x support. Before adopting, pin a specific release, read the version requirements section for that release against your own environment, and confirm that the estimator you need is in the complete list rather than one of the not started items.

## FAQ

### What does linearmodels add to statsmodels?

Panel models with fixed, random and first difference estimators, instrumental variable estimators including 2SLS, LIML, k-class, GMM and JIVE, factor asset pricing models, and system regression with SUR, 3SLS and GMM, plus specification tests such as Hausman, Pesaran CD, Cragg-Donald and Kleibergen-Paap.

### How do I install linearmodels?

Run pip install linearmodels. Binary wheels exist for Windows, macOS and Linux, and without a wheel pip builds from source, which needs a C compiler. Building the main branch instead uses meson-python with Cython, NumPy and setuptools_scm installed automatically by pip.

### How do I write an instrumental variable model in linearmodels?

Put the endogenous regressors and their instruments inside square brackets in the formula, with the tilde separating regressors from instruments. For example IV2SLS.from_formula('np.log(wage) ~ 1 + exper + exper ** 2 + [educ ~ motheduc + fatheduc]', data).

### Does linearmodels support dynamic panel models?

No. The plan and status section marks dynamic panel model estimation as not started, along with linear IV panel model estimation. The panel families that are complete are fixed effects, random effects, first difference, between, pooled and Fama-MacBeth.

## Sources

- [bashtage/linearmodels on GitHub](https://github.com/bashtage/linearmodels)
- [License: NCSA](https://github.com/bashtage/linearmodels/blob/main/LICENSE)
- [Project website](https://bashtage.github.io/linearmodels/)
- [README](https://github.com/bashtage/linearmodels/blob/main/README.md)
- [Releases](https://github.com/bashtage/linearmodels/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/bashtage-linearmodels
