regression_diagnostics/lib.rs
1//! # regression-diagnostics
2//!
3//! Statistical diagnostics for **ordinary least squares** regression models in
4//! Rust — the surface R's `car`/`lmtest` and Python's `statsmodels` expose, in a
5//! dependency-light crate. It fills the specific ecosystem gap that no maintained
6//! Rust crate offers Variance Inflation Factor, adjusted R², or residual
7//! diagnostics (autocorrelation, heteroskedasticity, normality, influence).
8//!
9//! Everything operates on a single fitted-model type, [`OlsFit`], computed once
10//! and reused by every diagnostic.
11//!
12//! ## Scope
13//!
14//! The core is **OLS diagnostics**, whose closed-form structure (a well-defined
15//! hat matrix and Gaussian residuals) is what makes them well-defined. Two
16//! further model families each get their own module, because their diagnostics
17//! are genuinely different — not reskinned OLS formulas:
18//!
19//! * [`regularized`] — ridge, lasso, **elastic net**, and **penalized
20//! logistic**, where the hat matrix changes (`H_λ = X(XᵀX + λI)⁻¹Xᵀ`) or does
21//! not exist in closed form; diagnostics are built on **effective degrees of
22//! freedom** and the **active set**.
23//! * [`logistic`] — binary logistic regression, a non-Gaussian likelihood with
24//! deviance/Pearson residuals, pseudo-R², and the Hosmer–Lemeshow test.
25//! * [`glm`] — the other exponential-family GLMs (Poisson, negative binomial,
26//! Gamma) behind one IRLS solver and a [`Family`](glm::Family) trait, with the
27//! same deviance/Pearson residual, dispersion, and influence diagnostics.
28//! * [`categorical`] — multinomial and ordinal (proportional-odds) logistic for
29//! multi-class responses, each reducing to binary logistic at `K = 2`.
30//! * [`survival`] — Cox proportional hazards (stratified and time-varying too),
31//! parametric accelerated-failure-time models, and Kaplan–Meier for censored
32//! time-to-event data, with martingale/deviance/Schoenfeld residuals.
33//! * [`mixed`] — random-intercept, random-slope, crossed and generalized
34//! (Laplace GLMM) mixed models for grouped data, with variance components, ICC,
35//! and BLUPs.
36//!
37//! ## Linear algebra
38//!
39//! Internals use `nalgebra` (pure-Rust QR/SVD, no system BLAS — chosen for
40//! portability); the public API speaks `ndarray`. That boundary and its tradeoff
41//! are documented in the README.
42//!
43//! ## Layout
44//!
45//! * [`OlsFit`] — the fitted model; constructed with [`OlsFit::new`] or
46//! [`OlsFit::with_intercept`]. **Read its intercept convention before use.**
47//! * [`multicollinearity`] — [`vif`](multicollinearity::vif),
48//! [`condition_number`](multicollinearity::condition_number).
49//! * [`fit_statistics`] — R²/adjusted R², F-statistic, AIC/BIC, log-likelihood.
50//! * [`residuals`] — Durbin-Watson, Breusch-Pagan, White, Jarque-Bera, the scaled
51//! residual forms, and QQ-plot data.
52//! * [`influence`] — leverage, Cook's distance, DFFITS.
53//! * [`coefficients`] — standardized (beta) coefficients.
54//! * [`Summary`] via [`OlsFit::summary`] — the one-call `statsmodels`-style report.
55//! * [`regularized`] — [`RidgeFit`](regularized::RidgeFit),
56//! [`LassoFit`](regularized::LassoFit),
57//! [`ElasticNetFit`](regularized::ElasticNetFit) and
58//! [`PenalizedLogisticFit`](regularized::PenalizedLogisticFit) with their
59//! shrinkage-aware diagnostics.
60//! * [`logistic`] — [`LogisticFit`](logistic::LogisticFit) with deviance/Pearson
61//! residuals, goodness-of-fit, Hosmer–Lemeshow, and logistic influence.
62//! * [`glm`] — [`GlmFit`](glm::GlmFit) over a [`Family`](glm::Family) (Poisson,
63//! negative binomial, Gamma), with residuals, dispersion, and influence.
64//! * [`categorical`] — [`MultinomialFit`](categorical::MultinomialFit) and
65//! [`OrdinalFit`](categorical::OrdinalFit) for multi-class responses.
66//! * [`survival`] — [`CoxFit`](survival::CoxFit) (with stratified and
67//! time-varying / counting-process forms), the parametric
68//! [`AftFit`](survival::AftFit), and [`KaplanMeier`](survival::KaplanMeier)
69//! with survival residuals.
70//! * [`mixed`] — [`LinearMixedModel`](mixed::LinearMixedModel) (closed-form
71//! random intercept), the general [`MixedModel`](mixed::MixedModel) (random
72//! slopes, crossed/nested), and [`GlmmFit`](mixed::GlmmFit) (Laplace GLMM),
73//! with variance components, ICC, and BLUPs.
74//!
75//! ## Quick start
76//!
77//! ```
78//! use ndarray::array;
79//! use regression_diagnostics::OlsFit;
80//! use regression_diagnostics::multicollinearity::vif;
81//!
82//! // Caller supplies the intercept column (first column of ones).
83//! let x = array![
84//! [1.0, 1.0, 2.0],
85//! [1.0, 2.0, 4.1],
86//! [1.0, 3.0, 5.9],
87//! [1.0, 4.0, 8.0],
88//! [1.0, 5.0, 10.1],
89//! ];
90//! let y = array![2.0, 4.1, 6.1, 8.0, 10.2];
91//! let fit = OlsFit::new(x, y).unwrap();
92//!
93//! println!("{}", fit.summary()); // full statsmodels-style report
94//! let v = vif(&fit); // per-predictor VIF (NaN for intercept)
95//! assert!(v[1].is_finite());
96//! ```
97
98#![warn(missing_docs)]
99#![forbid(unsafe_code)]
100
101mod fit;
102mod linalg;
103mod optimize;
104mod summary;
105
106pub mod categorical;
107pub mod coefficients;
108pub mod error;
109pub mod fit_statistics;
110pub mod glm;
111pub mod influence;
112pub mod logistic;
113pub mod mixed;
114pub mod multicollinearity;
115pub mod regularized;
116pub mod residuals;
117pub mod survival;
118
119pub use error::{RegressionError, Result};
120pub use fit::OlsFit;
121pub use summary::{CoefficientRow, Summary};