regdiag
R's plot(lm_model) for Python — one line, works with both statsmodels and scikit-learn.
R has a famous one-liner for regression diagnostics: plot(lm_model) produces four
classic diagnostic plots (Residuals vs Fitted, Normal Q-Q, Scale-Location, Residuals
vs Leverage). Python has never had a clean equivalent — the pieces exist scattered
across statsmodels (only works on its own OLS objects) and a few small,
low-traction packages. regdiag fills that gap.
from sklearn.linear_model import LinearRegression
import regdiag
model = LinearRegression().fit(X, y)
regdiag.diagnose(model, X, y)
Why regdiag
- One line, R-style output.
regdiag.diagnose(model, X, y)gives you the full 4-panel figure, same asplot(lm). - Works with statsmodels and scikit-learn. Any sklearn estimator exposing
.coef_/.intercept_(LinearRegression, Ridge, Lasso, ElasticNet, SGDRegressor, BayesianRidge, ...) or a statsmodelsOLSresults object. statsmodelsis fully optional. Core dependencies are just numpy, scipy, matplotlib, and scikit-learn. VIF and the Breusch-Pagan test are computed with plain numpy/scipy — no statsmodels needed at runtime, even though it's the library people usually reach for to get those numbers.- Honest about black-box models. Pass a
RandomForestRegressoror any other model that only exposes.predict()andregdiagswitches to a clearly-labeled generic mode (Residuals vs Fitted, Residual Distribution, Actual vs Predicted). It will never compute leverage or Cook's distance for a model where the hat-matrix math doesn't apply — those statistics are only well-defined for linear models.
Install
pip install regdiag
# with statsmodels support (accept statsmodels OLS objects as input):
pip install "regdiag[statsmodels]"
Quickstart
import numpy as np
from sklearn.linear_model import LinearRegression
import regdiag
rng = np.random.default_rng(0)
X = rng.normal(size=(200, 3))
y = 1.0 + X @ np.array([2.0, -1.5, 0.5]) + rng.normal(scale=1.0, size=200)
model = LinearRegression().fit(X, y)
diag = regdiag.diagnose(model, X, y) # fits nothing, model must already be fit; shows the 4-panel plot
print(diag.summary()) # Breusch-Pagan test, VIF table, top Cook's-distance points
Also works directly with statsmodels:
import statsmodels.api as sm
X_const = sm.add_constant(X)
results = sm.OLS(y, X_const).fit()
regdiag.diagnose(results, X, y)
And degrades gracefully for black-box models instead of lying about statistics:
from sklearn.ensemble import RandomForestRegressor
rf = RandomForestRegressor().fit(X, y)
diag = regdiag.diagnose(rf, X, y) # 3-panel generic residual analysis
diag.vif() # raises NotLinearModelError — VIF isn't defined here
API
regdiag.diagnose(model, X, y, *, feature_names=None, plot=True,
figsize=(10, 8), annotate=True, n_annotate=3, save=None)
Returns a RegressionDiagnostics object:
| Attribute / method | Linear mode | Generic mode |
|---|---|---|
.residuals, .fitted_values |
✅ | ✅ |
.leverage, .cooks_distance, .studentized_residuals |
✅ | None |
.plot() |
4-panel | 3-panel |
.residuals_vs_fitted(), .qq_plot(), .scale_location(), .residuals_vs_leverage() |
✅ | raises NotLinearModelError |
.residual_histogram(), .actual_vs_predicted() |
✅ | ✅ |
.breusch_pagan(), .vif() |
✅ | raises NotLinearModelError |
.summary() |
text report | text report |
Comparison
| regdiag | lmdiag | statsmodels (raw) | yellowbrick | |
|---|---|---|---|---|
| Works with sklearn linear models | ✅ | ✅ | ❌ | ✅ |
| Works with statsmodels OLS | ✅ | ✅ | ✅ | ❌ |
| statsmodels is optional at runtime | ✅ | ❌ | n/a | ✅ |
| Built-in VIF / Breusch-Pagan | ✅ | ❌ | ✅ (manual) | ❌ |
| Honest black-box fallback (no fake leverage) | ✅ | ❌ | ❌ | partial |
One-object API (diagnose(model, X, y)) |
✅ | functions | manual | partial |
Statistical notes
- Leverage is computed via QR decomposition of the design matrix (never forms the
full
n × nhat matrix). - Cook's distance uses the classic OLS-based formula. It's applied uniformly to any linear-coefficient model (including Ridge/Lasso) for simplicity, but strictly its "influence on fitted coefficients" interpretation assumes an OLS estimator — interpret with some caution for heavily regularized models.
- Rank-deficient design matrices (collinear columns) and
n ≤ pdatasets raise a clear error rather than emittingNaN/infsilently. statsmodelsWLS/GLS results are not supported in v1 (OLS only).
See CHANGELOG.md for release notes and CONTRIBUTING.md to get set up for
development.
License
MIT — see LICENSE.
Metadata
Release files for regdiag 0.1.2
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| regdiag-0.1.2.tar.gz | 242.4 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| regdiag-0.1.2-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 255.2 kB
Release files / regdiag-0.1.2.tar.gz
| Download URL | regdiag-0.1.2.tar.gz |
|---|---|
| Size | 242.4 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
05a8c73375f5dd43acfdd97f5f4f66e7f3d03c22ed961e78630ac9aba06a01c0
|
|
BLAKE2b-256 checksum How to use checksums |
5e7f24025a58d5aca771fad9d865e0b8a645dba30a416381dac1fa9a56d49b66
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.12
|
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 Jul 3, 2026.
Transparency logRelease files / regdiag-0.1.2-py3-none-any.whl
| Download URL | regdiag-0.1.2-py3-none-any.whl |
|---|---|
| Size | 12.8 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
b4edd90a2f6a9d39f20256cd9a35ca9d57cbe5cbe1069384c030ee78e34eb08c
|
|
BLAKE2b-256 checksum How to use checksums |
3aefd12bbfc32c503ae708026436eb2c6d5b141524077f014b88ca2f643c2fd7
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.12
|
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 Jul 3, 2026.
Transparency log