1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
//! # regression-diagnostics
//!
//! Statistical diagnostics for **ordinary least squares** regression models in
//! Rust — the surface R's `car`/`lmtest` and Python's `statsmodels` expose, in a
//! dependency-light crate. It fills the specific ecosystem gap that no maintained
//! Rust crate offers Variance Inflation Factor, adjusted R², or residual
//! diagnostics (autocorrelation, heteroskedasticity, normality, influence).
//!
//! Everything operates on a single fitted-model type, [`OlsFit`], computed once
//! and reused by every diagnostic.
//!
//! ## Scope
//!
//! The core is **OLS diagnostics**, whose closed-form structure (a well-defined
//! hat matrix and Gaussian residuals) is what makes them well-defined. Two
//! further model families each get their own module, because their diagnostics
//! are genuinely different — not reskinned OLS formulas:
//!
//! * [`regularized`] — ridge and lasso, where the hat matrix changes
//! (`H_λ = X(XᵀX + λI)⁻¹Xᵀ`) or does not exist in closed form; diagnostics are
//! built on **effective degrees of freedom** and the **active set**.
//! * [`logistic`] — binary logistic regression, a non-Gaussian likelihood with
//! deviance/Pearson residuals, pseudo-R², and the Hosmer–Lemeshow test.
//!
//! ## Linear algebra
//!
//! Internals use `nalgebra` (pure-Rust QR/SVD, no system BLAS — chosen for
//! portability); the public API speaks `ndarray`. That boundary and its tradeoff
//! are documented in the README.
//!
//! ## Layout
//!
//! * [`OlsFit`] — the fitted model; constructed with [`OlsFit::new`] or
//! [`OlsFit::with_intercept`]. **Read its intercept convention before use.**
//! * [`multicollinearity`] — [`vif`](multicollinearity::vif),
//! [`condition_number`](multicollinearity::condition_number).
//! * [`fit_statistics`] — R²/adjusted R², F-statistic, AIC/BIC, log-likelihood.
//! * [`residuals`] — Durbin-Watson, Breusch-Pagan, White, Jarque-Bera, the scaled
//! residual forms, and QQ-plot data.
//! * [`influence`] — leverage, Cook's distance, DFFITS.
//! * [`coefficients`] — standardized (beta) coefficients.
//! * [`Summary`] via [`OlsFit::summary`] — the one-call `statsmodels`-style report.
//! * [`regularized`] — [`RidgeFit`](regularized::RidgeFit) and
//! [`LassoFit`](regularized::LassoFit) with their shrinkage-aware diagnostics.
//! * [`logistic`] — [`LogisticFit`](logistic::LogisticFit) with deviance/Pearson
//! residuals, goodness-of-fit, Hosmer–Lemeshow, and logistic influence.
//!
//! ## Quick start
//!
//! ```
//! use ndarray::array;
//! use regression_diagnostics::OlsFit;
//! use regression_diagnostics::multicollinearity::vif;
//!
//! // Caller supplies the intercept column (first column of ones).
//! let x = array![
//! [1.0, 1.0, 2.0],
//! [1.0, 2.0, 4.1],
//! [1.0, 3.0, 5.9],
//! [1.0, 4.0, 8.0],
//! [1.0, 5.0, 10.1],
//! ];
//! let y = array![2.0, 4.1, 6.1, 8.0, 10.2];
//! let fit = OlsFit::new(x, y).unwrap();
//!
//! println!("{}", fit.summary()); // full statsmodels-style report
//! let v = vif(&fit); // per-predictor VIF (NaN for intercept)
//! assert!(v[1].is_finite());
//! ```
pub use ;
pub use OlsFit;
pub use ;