pub struct OlsFit { /* private fields */ }Expand description
A fitted ordinary-least-squares model: the shared representation every diagnostic in this crate is computed from.
§Intercept convention
The caller owns the design matrix X, including any intercept column.
This crate does not silently prepend a column of ones. There are two
constructors, and the choice is explicit at the call site:
OlsFit::newfits exactly the columns you pass. If one of them is constant it is auto-detected and treated as the intercept (this drives the centered-vs-uncenteredR²choice, and excludes that column from VIF); if none is constant the model is fit through the origin.OlsFit::with_interceptprepends a ones column for you and marks it as the intercept.
Getting this wrong silently corrupts every downstream diagnostic, so the convention is stated here rather than buried in the implementation.
§What is computed and cached
Construction performs a single QR factorization of X and caches the
coefficients, fitted values, residuals, leverage vector diag(H), (XᵀX)⁻¹,
the design’s singular values, and the residual variance. Diagnostics read
these cached quantities rather than refactorizing.
Coefficients are obtained by a QR solve of X, never by inverting XᵀX
— that matters for the multicollinearity diagnostics specifically, since
forming XᵀX squares the condition number they exist to measure. Leverage is
read from the thin Q factor, so the full n × n hat matrix is never formed.
§Example
use ndarray::{array, Array2};
use regression_diagnostics::OlsFit;
// y = 1 + 2*x exactly; supply the intercept ourselves.
let x = array![[1.0, 0.0], [1.0, 1.0], [1.0, 2.0], [1.0, 3.0]];
let y = array![1.0, 3.0, 5.0, 7.0];
let fit = OlsFit::new(x, y).unwrap();
assert!((fit.coefficients()[0] - 1.0).abs() < 1e-9);
assert!((fit.coefficients()[1] - 2.0).abs() < 1e-9);Implementations§
Source§impl OlsFit
impl OlsFit
Sourcepub fn new(x: Array2<f64>, y: Array1<f64>) -> Result<Self>
pub fn new(x: Array2<f64>, y: Array1<f64>) -> Result<Self>
Fit y ~ X by OLS, using the columns of X exactly as given.
A constant column, if present, is auto-detected as the intercept. See the type-level docs for the full convention.
§Errors
RegressionError::EmptyInputifXoryis empty.RegressionError::ShapeMismatchifX.nrows() != y.len().RegressionError::NoResidualDegreesOfFreedomifn <= p.RegressionError::RankDeficientif the columns are collinear.
Sourcepub fn with_intercept(x: Array2<f64>, y: Array1<f64>) -> Result<Self>
pub fn with_intercept(x: Array2<f64>, y: Array1<f64>) -> Result<Self>
Fit y ~ [1 | X] by OLS, prepending a column of ones as the intercept.
Errors are the same as OlsFit::new, evaluated against the augmented
design (so a design with n == p_original + 1 will fail the
residual-degrees-of-freedom check).
Sourcepub fn n_observations(&self) -> usize
pub fn n_observations(&self) -> usize
Number of observations n.
Sourcepub fn n_parameters(&self) -> usize
pub fn n_parameters(&self) -> usize
Number of model parameters p (design-matrix columns, intercept
included if present).
Sourcepub fn has_intercept(&self) -> bool
pub fn has_intercept(&self) -> bool
Whether the model includes an intercept (constant) column.
Sourcepub fn intercept_column(&self) -> Option<usize>
pub fn intercept_column(&self) -> Option<usize>
Index of the intercept column within the design matrix, if any.
Sourcepub fn design_matrix(&self) -> ArrayView2<'_, f64>
pub fn design_matrix(&self) -> ArrayView2<'_, f64>
The design matrix X as fitted (with the intercept column if one was
added or detected).
Sourcepub fn response(&self) -> ArrayView1<'_, f64>
pub fn response(&self) -> ArrayView1<'_, f64>
The response vector y.
Sourcepub fn coefficients(&self) -> ArrayView1<'_, f64>
pub fn coefficients(&self) -> ArrayView1<'_, f64>
Estimated coefficients, one per design-matrix column.
Sourcepub fn fitted_values(&self) -> ArrayView1<'_, f64>
pub fn fitted_values(&self) -> ArrayView1<'_, f64>
Fitted values ŷ = X β.
Sourcepub fn residuals(&self) -> ArrayView1<'_, f64>
pub fn residuals(&self) -> ArrayView1<'_, f64>
Raw residuals e = y − ŷ.
Sourcepub fn leverage(&self) -> ArrayView1<'_, f64>
pub fn leverage(&self) -> ArrayView1<'_, f64>
Leverage vector diag(H). Each entry lies in [0, 1] and the vector
sums to p (the number of parameters) — a standard identity worth
checking as a correctness probe.
Sourcepub fn residual_sum_of_squares(&self) -> f64
pub fn residual_sum_of_squares(&self) -> f64
Residual sum of squares Σ eᵢ².
Sourcepub fn df_residual(&self) -> f64
pub fn df_residual(&self) -> f64
Residual degrees of freedom n − p.
Sourcepub fn residual_variance(&self) -> f64
pub fn residual_variance(&self) -> f64
Unbiased residual variance estimate s² = RSS / (n − p).
Sourcepub fn residual_standard_error(&self) -> f64
pub fn residual_standard_error(&self) -> f64
Residual standard error s = √(RSS / (n − p)).
Sourcepub fn coefficient_standard_errors(&self) -> Array1<f64>
pub fn coefficient_standard_errors(&self) -> Array1<f64>
Standard errors of the coefficients: sⱼ = s · √((XᵀX)⁻¹ⱼⱼ).
Sourcepub fn singular_values(&self) -> &[f64]
pub fn singular_values(&self) -> &[f64]
Singular values of the design matrix, in descending order.
Source§impl OlsFit
impl OlsFit
Sourcepub fn summary(&self) -> Summary
pub fn summary(&self) -> Summary
Compute the full Summary for this fit — every statistic in Milestones
2–6 in one call.
use ndarray::array;
use regression_diagnostics::OlsFit;
let x = array![[1.0, 0.0], [1.0, 1.0], [1.0, 2.0], [1.0, 3.0], [1.0, 4.0]];
let y = array![1.0, 3.1, 4.9, 7.0, 9.1];
let fit = OlsFit::new(x, y).unwrap();
let s = fit.summary();
println!("{s}");
assert!(s.r_squared > 0.99);Trait Implementations§
Auto Trait Implementations§
impl Freeze for OlsFit
impl RefUnwindSafe for OlsFit
impl Send for OlsFit
impl Sync for OlsFit
impl Unpin for OlsFit
impl UnsafeUnpin for OlsFit
impl UnwindSafe for OlsFit
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
impl<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> Read<Exclusive, BecauseExclusive> for Twhere
T: ?Sized,
Source§impl<SS, SP> SupersetOf<SS> for SPwhere
SS: SubsetOf<SP>,
impl<SS, SP> SupersetOf<SS> for SPwhere
SS: SubsetOf<SP>,
Source§fn to_subset(&self) -> Option<SS>
fn to_subset(&self) -> Option<SS>
self from the equivalent element of its
superset. Read moreSource§fn is_in_subset(&self) -> bool
fn is_in_subset(&self) -> bool
self is actually part of its subset T (and can be converted to it).Source§fn to_subset_unchecked(&self) -> SS
fn to_subset_unchecked(&self) -> SS
self.to_subset but without any property checks. Always succeeds.Source§fn from_subset(element: &SS) -> SP
fn from_subset(element: &SS) -> SP
self to the equivalent element of its superset.Source§impl<SS, SP> SupersetOf<SS> for SPwhere
SS: SubsetOf<SP>,
impl<SS, SP> SupersetOf<SS> for SPwhere
SS: SubsetOf<SP>,
Source§fn to_subset(&self) -> Option<SS>
fn to_subset(&self) -> Option<SS>
self from the equivalent element of its
superset. Read moreSource§fn is_in_subset(&self) -> bool
fn is_in_subset(&self) -> bool
self is actually part of its subset T (and can be converted to it).Source§fn to_subset_unchecked(&self) -> SS
fn to_subset_unchecked(&self) -> SS
self.to_subset but without any property checks. Always succeeds.Source§fn from_subset(element: &SS) -> SP
fn from_subset(element: &SS) -> SP
self to the equivalent element of its superset.