1use crate::statistics::Statistics;
4use crate::vector::Vector;
5use comfy_table::{Cell, Table};
6use num_traits::Float;
7use std::fmt;
8
9pub struct Summary<T> {
11 pub count: usize,
13 pub mean: Option<T>,
15 pub stddev: Option<T>,
17 pub min: Option<T>,
19 pub q25: Option<T>,
21 pub median: Option<T>,
23 pub q75: Option<T>,
25 pub max: Option<T>,
27}
28
29impl<T> fmt::Display for Summary<T>
30where
31 T: Float + fmt::Display,
32{
33 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
34 let mut table = Table::new();
35 table.set_header(vec!["Statistic", "Value"]);
36
37 table.add_row(vec![Cell::new("Count"), Cell::new(self.count)]);
38 table.add_row(vec![
39 Cell::new("Mean"),
40 Cell::new(format!("{:.4}", self.mean.unwrap_or(T::nan()))),
41 ]);
42 table.add_row(vec![
43 Cell::new("Std Dev"),
44 Cell::new(format!("{:.4}", self.stddev.unwrap_or(T::nan()))),
45 ]);
46 table.add_row(vec![
47 Cell::new("Min"),
48 Cell::new(format!("{:.4}", self.min.unwrap_or(T::nan()))),
49 ]);
50 table.add_row(vec![
51 Cell::new("25%"),
52 Cell::new(format!("{:.4}", self.q25.unwrap_or(T::nan()))),
53 ]);
54 table.add_row(vec![
55 Cell::new("Median"),
56 Cell::new(format!("{:.4}", self.median.unwrap_or(T::nan()))),
57 ]);
58 table.add_row(vec![
59 Cell::new("75%"),
60 Cell::new(format!("{:.4}", self.q75.unwrap_or(T::nan()))),
61 ]);
62 table.add_row(vec![
63 Cell::new("Max"),
64 Cell::new(format!("{:.4}", self.max.unwrap_or(T::nan()))),
65 ]);
66
67 write!(f, "{}", table)
68 }
69}
70
71pub trait SummaryOps<T> {
73 fn summary(&self) -> Summary<T>;
74}
75
76impl<T> SummaryOps<T> for Vector<T>
77where
78 T: Float + Copy + PartialOrd + fmt::Display,
79{
80 fn summary(&self) -> Summary<T> {
81 Summary {
82 count: self.len(),
83 mean: self.mean(),
84 stddev: self.stddev(),
85 min: self.min(),
86 q25: self.quantile(T::from(0.25).unwrap()),
87 median: self.median(),
88 q75: self.quantile(T::from(0.75).unwrap()),
89 max: self.max(),
90 }
91 }
92}