average/moments/
kurtosis.rs1#[derive(Debug, Clone)]
6#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7pub struct Kurtosis {
8 avg: Skewness,
10 sum_4: f64,
12}
13
14impl Kurtosis {
15 #[inline]
17 pub fn new() -> Kurtosis {
18 Kurtosis {
19 avg: Skewness::new(),
20 sum_4: 0.,
21 }
22 }
23
24 #[inline]
28 fn increment(&mut self) {
29 self.avg.increment();
30 }
31
32 #[inline]
38 fn add_inner(&mut self, delta: f64, delta_n: f64) {
39 let n = self.len().to_f64().unwrap();
43 let term = delta * delta_n * (n - 1.);
44 let delta_n_sq = delta_n*delta_n;
45 self.sum_4 += term * delta_n_sq * (n*n - 3.*n + 3.)
46 + 6. * delta_n_sq * self.avg.avg.sum_2
47 - 4. * delta_n * self.avg.sum_3;
48 self.avg.add_inner(delta, delta_n);
49 }
50
51 #[inline]
53 pub fn is_empty(&self) -> bool {
54 self.avg.is_empty()
55 }
56
57 #[inline]
61 pub fn mean(&self) -> f64 {
62 self.avg.mean()
63 }
64
65 #[inline]
67 pub fn len(&self) -> u64 {
68 self.avg.len()
69 }
70
71 #[inline]
77 pub fn sample_variance(&self) -> f64 {
78 self.avg.sample_variance()
79 }
80
81 #[inline]
87 pub fn population_variance(&self) -> f64 {
88 self.avg.population_variance()
89 }
90
91 #[inline]
93 pub fn error_mean(&self) -> f64 {
94 self.avg.error_mean()
95 }
96
97 #[inline]
101 pub fn skewness(&self) -> f64 {
102 self.avg.skewness()
103 }
104
105 #[inline]
109 pub fn kurtosis(&self) -> f64 {
110 if self.is_empty() {
111 return f64::NAN;
112 }
113 if self.sum_4 == 0. {
114 return 0.;
115 }
116 let n = self.len().to_f64().unwrap();
117 debug_assert_ne!(self.avg.avg.sum_2, 0.);
118 n * self.sum_4 / (self.avg.avg.sum_2 * self.avg.avg.sum_2) - 3.
119 }
120
121}
122
123impl core::default::Default for Kurtosis {
124 fn default() -> Kurtosis {
125 Kurtosis::new()
126 }
127}
128
129impl Estimate for Kurtosis {
130 #[inline]
131 fn add(&mut self, x: f64) {
132 let delta = x - self.avg.avg.avg.avg;
133 self.increment();
134 let n = self.len().to_f64().unwrap();
135 self.add_inner(delta, delta/n);
136 }
137
138 #[inline]
139 fn estimate(&self) -> f64 {
140 self.kurtosis()
141 }
142}
143
144impl Merge for Kurtosis {
145 #[inline]
146 fn merge(&mut self, other: &Kurtosis) {
147 if other.is_empty() {
148 return;
149 }
150 if self.is_empty() {
151 *self = other.clone();
152 return;
153 }
154 let len_self = self.len().to_f64().unwrap();
155 let len_other = other.len().to_f64().unwrap();
156 let len_total = len_self + len_other;
157 let delta = other.mean() - self.mean();
158 let delta_n = delta / len_total;
159 let delta_n_sq = delta_n * delta_n;
160 self.sum_4 += other.sum_4
161 + delta * delta_n*delta_n_sq * len_self*len_other
162 * (len_self*len_self - len_self*len_other + len_other*len_other)
163 + 6.*delta_n_sq * (len_self*len_self * other.avg.avg.sum_2 + len_other*len_other * self.avg.avg.sum_2)
164 + 4.*delta_n * (len_self * other.avg.sum_3 - len_other * self.avg.sum_3);
165 self.avg.merge(&other.avg);
166 }
167}
168
169impl_from_iterator!(Kurtosis);
170impl_from_par_iterator!(Kurtosis);
171impl_extend!(Kurtosis);