regression-diagnostics 0.2.0

Statistical diagnostics for OLS regression in Rust: VIF, condition number, adjusted R2, F/AIC/BIC, residual tests (Durbin-Watson, Breusch-Pagan, White, Jarque-Bera), influence measures (leverage, Cook's distance, DFFITS), QQ-plot data, and an R/statsmodels-style summary().
Documentation
use crate::OlsFit;

/// Durbin-Watson statistic for first-order residual autocorrelation.
///
/// `DW = Σₜ₌₂ⁿ (eₜ − eₜ₋₁)² / Σₜ eₜ²`, ranging in `[0, 4]`: values near **2**
/// indicate no autocorrelation, near **0** strong positive autocorrelation, near
/// **4** strong negative.
///
/// # Ordering assumption
///
/// This statistic only means something if the observations are in a meaningful
/// order — time, or a spatial sequence. On data with no natural ordering it is
/// **not a valid diagnostic**: reordering the rows would change the value while
/// the model is identical. It is most relevant in the time-series setting (see
/// the guide's Time Series chapter); for cross-sectional data reach for a
/// heteroskedasticity or normality test instead.
pub fn durbin_watson(fit: &OlsFit) -> f64 {
    let e = fit.residuals();
    let denom: f64 = e.iter().map(|v| v * v).sum();
    if denom <= 0.0 {
        return f64::NAN;
    }
    let mut num = 0.0;
    for t in 1..e.len() {
        let d = e[t] - e[t - 1];
        num += d * d;
    }
    num / denom
}