tktax_stats/
txn_summary_stats.rs

1// ---------------- [ File: tktax-stats/src/txn_summary_stats.rs ]
2crate::ix!();
3
4pub fn print_categorized_transaction_summary_statistics(txns: &[&Transaction]) {
5
6    match TxSummaryStatistics::create_if_nonempty(txns) {
7        Some(stats) => println!("{}", stats),
8        None        => {}
9    }
10}
11
12//---------------------------------------
13#[derive(Getters,Clone,Debug)]
14#[getset(get="pub")]
15pub struct TxSummaryStatistics {
16    count:                usize,
17    min:                  MonetaryAmount,
18    max:                  MonetaryAmount,
19    midrange:             MonetaryAmount,
20    average:              MonetaryAmount,
21    median:               MonetaryAmount,
22    repeated:             Vec<(MonetaryAmount,usize)>,
23    standard_deviation:   MonetaryAmount,
24    quartiles_iqr:        MoneyQuartiles,
25    outliers_iqr:         Vec<MonetaryAmount>,
26    skewness:             Dimensionless,
27    kurtosis:             Dimensionless,
28    cumulative_frequency: Vec<MonetaryAmount>,
29}
30
31impl fmt::Display for TxSummaryStatistics {
32
33    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
34
35        const DO_CUMULATIVE_FREQUENCY: bool = false;
36        const DO_REPEATED:             bool = true;
37        const DO_QUARTILES_IQR:        bool = true;
38        const DO_OUTLIERS_IQR:         bool = true;
39
40        writeln!(f, "~ ------------[summary stats]------------ ~")?;
41
42        writeln!(f, "count:                {:?}", self.count)?;
43        writeln!(f, "min:                  {:?}", self.min)?;
44        writeln!(f, "max:                  {:?}", self.max)?;
45        writeln!(f, "avg:                  {:?}", self.average)?;
46        writeln!(f, "midrange:             {:?}", self.midrange)?;
47        writeln!(f, "median:               {:?}", self.median)?;
48        writeln!(f, "standard dev:         {:?}", self.standard_deviation)?;
49        writeln!(f, "skewness:             {}",   self.skewness)?;
50        writeln!(f, "kurtosis:             {}",   self.kurtosis)?;
51
52        if DO_REPEATED {
53            if self.repeated.is_empty() {
54                writeln!(f, "<no repeated transaction amounts>")?;
55            } else {
56                writeln!(f, "repeated:")?;
57                for item in self.repeated.iter() {
58                    writeln!(f, "  {:<3}@{}", item.1, item.0)?;
59                }
60                //writeln!(f,"")?;
61            }
62        }
63
64        if DO_QUARTILES_IQR {
65            writeln!(f, "quartiles_iqr:")?;
66            writeln!(f, "  {}", self.quartiles_iqr.0)?;
67            writeln!(f, "  {}", self.quartiles_iqr.1)?;
68            writeln!(f, "  {}", self.quartiles_iqr.2)?;
69            writeln!(f, "  {}", self.quartiles_iqr.3)?;
70            writeln!(f,"")?;
71        }
72
73        if DO_OUTLIERS_IQR {
74            if self.outliers_iqr.is_empty() {
75                writeln!(f, "<no iqr outliers detected>")?;
76            } else {
77                writeln!(f, "outliers_iqr:")?;
78                for item in self.outliers_iqr.iter() {
79                    writeln!(f, "  {}", item)?;
80                }
81                //writeln!(f,"")?;
82            }
83        }
84
85        if DO_CUMULATIVE_FREQUENCY {
86            assert!(!self.cumulative_frequency.is_empty());
87            writeln!(f, "cumulative_frequency:")?;
88            for item in self.cumulative_frequency.iter() {
89                writeln!(f, "  {}", item)?;
90            }
91            //writeln!(f,"")?;
92        }
93
94        Ok(())
95    }
96}
97
98impl TxSummaryStatistics {
99
100    pub fn create_if_nonempty(txns: &[&Transaction]) -> Option<Self> {
101
102        if txns.is_empty() {
103            return None;
104        }
105
106        let amounts: Vec<MonetaryAmount> = txns.iter().map(|tx| tx.amount()).collect();
107
108        Some(Self {
109            count:                amounts.len(),
110            min:                  amounts.min_value().ok()?,
111            max:                  amounts.max_value().ok()?,
112            midrange:             amounts.midrange().ok()?,
113            average:              amounts.mean().ok()?,
114            median:               amounts.median().ok()?,
115            repeated:             amounts.repeated_values().ok()?,
116            standard_deviation:   amounts.stddev().ok()?,
117            quartiles_iqr:        amounts.quartiles_iqr().ok()?,
118            outliers_iqr:         amounts.outliers_iqr().ok()?,
119            skewness:             amounts.skewness().ok()?,
120            kurtosis:             amounts.kurtosis().ok()?,
121            cumulative_frequency: amounts.cumulative_frequency().ok()?,
122        })
123    }
124}