Skip to main content

pyLGM

General-purpose latent Gaussian models for Python — the model class behind INLA.
Deterministic Bayesian inference for structured data. No MCMC, no new dependencies.

PyPI Python versions CI Docs License Ruff

Documentation · How it works · Comparison · Examples · Theory


What it does

Declare structure — groups, space, time, frequency, networks — and pyLGM returns a posterior for each component, not just a prediction. Fits run in seconds through Laplace approximations and INLA-style integration, and are deterministic: same data, same answer, no convergence diagnostics.

Besag smoothing shrinks noisy rates toward local means

Partial pooling in one picture: noisy small-area rates (left, near zero) are pulled toward their neighbours, while well-observed areas keep their signal. Marker size is the expected count. From the disease-mapping example.

Install

pip install pylgm
pip install "pylgm[spark]"   # optional: Spark data boundary

Requires Python ≥ 3.11.

30-second example

A Poisson model with a per-region random intercept, fit with the Laplace engine:

import pandas as pd
from pylgm import Fixed, IID, LGM, Poisson

frame = pd.DataFrame({
    "region": ["north", "north", "north", "south", "south", "south"],
    "time":   [1, 2, 3, 1, 2, 3],
    "x":      [0.0, 0.5, 1.0, 0.0, 0.5, 1.0],
    "count":  [3, 5, 8, 2, 3, 5],
})

model = LGM(
    response="count",
    likelihood=Poisson(),                                # canonical log link
    predictor=Fixed("1 + x")                             # fixed effects
        + IID("region", index="region", precision=2.0),  # random intercept per region
    panel=("region",),
    time="time",
)

result = model.fit(frame, engine="laplace")
print("fitted_mean:", result.fitted_mean.round(3).tolist())
# fitted_mean: [3.254, 4.986, 8.15, 2.201, 3.373, 5.513]

The same model can be declared in YAML and loaded with pylgm.config.load_model.

Reproducing a published result

examples/columbus_spatial_econometrics reproduces the reference result of spatial econometrics — Anselin (1988), Table 12.1, 49 Columbus OH neighbourhoods:

model const INC HOVAL ρ / λ
published OLS 68.619 −1.5973 −0.2739 —
OLS, recomputed 68.619 −1.5973 −0.2739 —
published ML spatial error 60.279 −0.9573 −0.3046 0.5468
pyLGM SAR 59.543 −0.9057 −0.3058 0.5946

OLS matching the published numbers exactly verifies the data and spec; the SAR fit then lands next to the published ML spatial-error estimates, and recovers the finding that ignoring spatial correlation overstates the income effect by 1.76×.

A network that changes every year

examples/state_income_dynamic_network fits 48 US states over 1997–2007 with one network per year, then knocks out 20% of the panel and restores it:

method RMSE ↓ (log income)
DynamicSpatialPanel 0.0246
state mean 0.1214
year mean 0.1484

~5× closer than the obvious baselines. The same example reports where it loses — a last-value forecast beats it on level forecasts, because the fitted γ ≈ 1 says log income is near a random walk.

Why not just use XGBoost?

Often you should — and the comparison page says so with measured numbers rather than adjectives. Both problems below are simulated, so the true surface is known and scored directly:

Problem pyLGM XGBoost GLM
200 areas, 3 counts each, smooth spatial signal (RMSE ↓) 0.135 0.371 0.429
4000 rows, nonlinear covariate interactions (RMSE ↓) 2.839 0.293 —

pyLGM wins where the per-unit sample is thin but the units are related, and returns 95% intervals that cover the truth 99% of the time. Gradient boosting wins where the signal is interactions among covariates and you have the rows to learn them. Reproduce both with examples/method_comparison.

What's in the box

Area What you get Docs
Likelihoods Gaussian (exact), Poisson, Bernoulli, Binomial, negative-binomial, Gamma, Beta, Weibull/exponential survival likelihoods
Effects Fixed, IID, RW1/RW2, AR1 (optionally group-wise), Seasonal, MIDAS, MIDASParametric, SpaceTime effects
Spatial Besag (ICAR), ProperCAR, BYM2, weighted graphs spatial
Networks directed SAR, dynamic DynamicSpatialPanel (SDPD) with forward forecasting spatial
Scale sparse solver past the dense guard, with the full uncertainty surface internals
Hyperparameters Empirical Bayes (type-II ML), MAP-II with PC priors, bounds empirical bayes
Integration INLA grid quadrature, simplified/full-Laplace marginals, DIC/WAIC/CPO/PIT INLA
Prediction fit-row, out-of-sample predict, and forecasting via NaN rows prediction
Constraints arbitrary linear constraints A x = e (R-INLA extraconstr) effects
Data boundary Pandas, or Spark / Databricks spark

Documentation

Full docs: https://ardea00.github.io/pylgm/

  • How it works — one fit() call end to end, then prediction and forecasting
  • Comparison — against regression, gradient boosting and MCMC, including where pyLGM loses
  • Theory — the model class and every structured effect, with references
  • Examples — 21 runnable scripts

Roadmap

What's shipped and what's next is on the roadmap; scope and compatibility policy on the internals page.

Contributing

Issues and pull requests welcome — see docs/development.md for the test setup. main is protected: PRs need the full CI matrix green before merge.

License

MIT

Release files for pylgm 0.6.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for pylgm 0.6.0
File Size Uploaded
pylgm-0.6.0.tar.gz 849.4 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for pylgm 0.6.0
File Interpreter ABI Platform
pylgm-0.6.0-py3-none-any.whl Python 3 none any Details

Total release size: 1.0 MB

Release files / pylgm-0.6.0.tar.gz

Download URL pylgm-0.6.0.tar.gz
Size 849.4 kB
Tags Source
SHA-256 checksum
How to use checksums
c3110a3698e7aad3bc2d4bf8233112d59bb68210ab585b3a997785a4e3c650d7
BLAKE2b-256 checksum
How to use checksums
cc63f6cfd235f340accaff068f380bc44902f9522cd3a41a4818659f7a2813c4
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Aug 30, 2026.

Transparency log

Release files / pylgm-0.6.0-py3-none-any.whl

Download URL pylgm-0.6.0-py3-none-any.whl
Size 154.6 kB
Tags Python 3
SHA-256 checksum
How to use checksums
ce7b0594addacdcdb8765bb39dbfc2b4f496478d26907e6d280c597ee94ac73d
BLAKE2b-256 checksum
How to use checksums
170aed625377d0b0ad3f4eccdb7b949756586c1b6400d5987c07fb47d0fbd3ee
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Aug 30, 2026.

Transparency log

Release history Release notifications | RSS feed

0.6.1

2 release files

This release

0.6.0 This release

2 release files

0.5.0

2 release files

0.4.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page