tktax_stats/
txn_summary_stats.rs1crate::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#[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 }
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 }
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 }
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}