regression_diagnostics/fit_statistics/
f_statistic.rs1use statrs::distribution::{ContinuousCDF, FisherSnedecor};
2
3use super::total_sum_of_squares;
4use crate::OlsFit;
5
6#[derive(Debug, Clone, Copy, PartialEq)]
8pub struct FStatistic {
9 pub statistic: f64,
11 pub df_model: f64,
13 pub df_residual: f64,
15 pub p_value: f64,
17}
18
19pub fn f_statistic(fit: &OlsFit) -> FStatistic {
29 let df_model = fit.df_model();
30 let df_residual = fit.df_residual();
31 let tss = total_sum_of_squares(fit);
32 let rss = fit.residual_sum_of_squares();
33 let explained = tss - rss;
34
35 if df_model <= 0.0 || df_residual <= 0.0 || rss <= 0.0 {
36 return FStatistic {
37 statistic: f64::NAN,
38 df_model,
39 df_residual,
40 p_value: f64::NAN,
41 };
42 }
43
44 let statistic = (explained / df_model) / (rss / df_residual);
45 let p_value = match FisherSnedecor::new(df_model, df_residual) {
46 Ok(dist) if statistic.is_finite() && statistic >= 0.0 => 1.0 - dist.cdf(statistic),
47 _ => f64::NAN,
48 };
49
50 FStatistic {
51 statistic,
52 df_model,
53 df_residual,
54 p_value,
55 }
56}