1#![doc=include_str!("../README.md")]
2#![deny(warnings, missing_docs, unsafe_code)]
3
4pub mod argsort;
5pub mod fill_nan;
6pub mod mean;
7pub mod median;
8pub mod normalize;
9pub mod range;
10pub mod rank;
11pub mod stddev;
12pub mod sum_of_squares;
13pub mod variance;
14mod welford_online;
15pub mod zscore;
16
17use argsort::{ArgSort, ArgSortIter};
18pub use fill_nan::FillNan;
19use fill_nan::FillNanIter;
20pub use mean::Mean;
21pub use median::Median;
22pub use normalize::Normalize;
23use normalize::NormalizeIter;
24use range::Range;
25use rank::{Rank, RankIter};
26pub use stddev::StdDev;
27pub use sum_of_squares::SumOfSquares;
28pub use variance::Variance;
29pub use zscore::ZScore;
30use zscore::ZScoreIter;
31
32pub trait Iterstats<A>: Iterator {
50 fn mean(self) -> <A as Mean>::Output
52 where
53 Self: Sized + Iterator<Item = A> + Clone,
54 A: Mean,
55 {
56 A::mean(self)
57 }
58
59 fn variance(self) -> <A as Variance>::Output
61 where
62 Self: Sized + Iterator<Item = A>,
63 A: Variance,
64 {
65 A::variance(self)
66 }
67
68 fn stddev(self) -> <A as StdDev>::Output
70 where
71 Self: Sized + Iterator<Item = A>,
72 A: StdDev,
73 {
74 A::stddev(self)
75 }
76
77 fn zscore(self) -> ZScoreIter<<A as ZScore>::Output>
79 where
80 Self: Sized + Iterator<Item = A> + Clone,
81 A: ZScore,
82 {
83 A::zscore(self)
84 }
85
86 fn normalize(
96 self,
97 min: <A as Normalize>::Output,
98 max: <A as Normalize>::Output,
99 ) -> NormalizeIter<<A as Normalize>::Output>
100 where
101 Self: Sized + Iterator<Item = A> + Clone,
102 A: Normalize,
103 {
104 A::normalize(self, min, max)
105 }
106
107 fn sum_of_squares(self) -> <A as SumOfSquares>::Output
109 where
110 Self: Sized + Iterator<Item = A>,
111 A: SumOfSquares,
112 {
113 A::sum_of_squares(self)
114 }
115
116 fn median(self) -> <A as Median>::Output
121 where
122 Self: Sized + Iterator<Item = A>,
123 A: Median,
124 {
125 A::median(self)
126 }
127
128 fn range(self) -> Option<(<A as Range>::Output, <A as Range>::Output)>
133 where
134 Self: Sized + Iterator<Item = A>,
135 A: Range,
136 {
137 A::range(self)
138 }
139
140 fn fill_nan(
142 self,
143 repl: <A as FillNan>::Output,
144 ) -> FillNanIter<impl Iterator<Item = <A as FillNan>::Output>, <A as FillNan>::Output>
145 where
146 Self: Sized + Iterator<Item = A>,
147 A: FillNan,
148 {
149 A::fill_nan(self, repl)
150 }
151
152 fn argsort(self) -> ArgSortIter<<A as ArgSort>::Output>
154 where
155 Self: Sized + Iterator<Item = A>,
156 A: ArgSort,
157 {
158 A::argsort(self)
159 }
160
161 fn rank(self) -> RankIter
163 where
164 Self: Sized + Iterator<Item = A>,
165 A: Rank,
166 {
167 A::rank(self)
168 }
169}
170
171impl<I, A> Iterstats<A> for I where I: Iterator + ?Sized {}
172
173#[cfg(test)]
174mod tests {
175 use super::*;
176
177 #[test]
178 fn mean() {
179 let data = [1., 2., 3., 4.];
180 let exp = 2.5;
181 assert_eq!(data.iter().mean(), exp);
182 assert_eq!(data.into_iter().mean(), exp);
183 }
184
185 #[test]
186 fn variance() {
187 let data = [1., 2., 3., 4.];
188 let exp = 1.25;
189 assert_eq!(data.iter().variance(), exp);
190 assert_eq!(data.into_iter().variance(), exp);
191 }
192
193 #[test]
194 fn stddev() {
195 let data = [1., 2., 3., 4.];
196 let exp = 1.25f64.sqrt();
197 assert_eq!(data.iter().stddev(), exp);
198 assert_eq!(data.into_iter().stddev(), exp);
199 }
200
201 #[test]
202 fn zscore() {
203 let data = [1., 2., 3., 4.];
204 let exp = vec![
205 -1.3416407864998738,
206 -0.4472135954999579,
207 0.4472135954999579,
208 1.3416407864998738,
209 ];
210 assert_eq!(data.iter().zscore().collect::<Vec<_>>(), exp);
211 assert_eq!(data.into_iter().zscore().collect::<Vec<_>>(), exp);
212 }
213
214 #[test]
215 fn normalize() {
216 let data = [1., 2., 3., 5.];
217 let normmin = 0.;
218 let normmax = 1.;
219 let exp = vec![0., 0.25, 0.5, 1.];
220 assert_eq!(
221 data.iter().normalize(normmin, normmax).collect::<Vec<_>>(),
222 exp
223 );
224 assert_eq!(
225 data.into_iter()
226 .normalize(normmin, normmax)
227 .collect::<Vec<_>>(),
228 exp
229 );
230 }
231
232 #[test]
233 fn sum_of_squares() {
234 let data = [1., 2., 3., 5.];
235 let exp = 8.75;
236 assert_eq!(data.iter().sum_of_squares(), exp);
237 assert_eq!(data.into_iter().sum_of_squares(), exp);
238 }
239
240 #[test]
241 fn median() {
242 let data = [2, 7, 198, 2, 2, 7];
243 let exp = 4;
244 assert_eq!(data.iter().median(), exp);
245 assert_eq!(data.into_iter().median(), exp);
246 }
247
248 #[test]
249 fn range() {
250 let data = [2, 7, -198, 2, 7];
251 let exprange = (-198, 7);
252 assert_eq!(data.iter().range().unwrap(), exprange);
253 assert_eq!(data.into_iter().range().unwrap(), exprange);
254 }
255
256 #[test]
257 fn fillnan() {
258 let data = [1., 100., 2., f32::NAN, 3., 5.];
259 let fill = 100.;
260 let exp = vec![1., 100., 2., 100., 3., 5.];
261 assert_eq!(data.iter().fill_nan(fill).collect::<Vec<_>>(), exp);
262 assert_eq!(data.into_iter().fill_nan(fill).collect::<Vec<_>>(), exp);
263 }
264
265 #[test]
266 fn argsort() {
267 let data = [
268 f64::NAN,
269 4.2,
270 0.0,
271 f64::NEG_INFINITY,
272 -0.0,
273 f64::INFINITY,
274 -f64::NAN,
275 ];
276 let exp = vec![6, 3, 4, 2, 1, 5, 0];
277 assert_eq!(data.iter().argsort().collect::<Vec<_>>(), exp);
278 assert_eq!(data.into_iter().argsort().collect::<Vec<_>>(), exp);
279 }
280
281 #[test]
282 fn rank() {
283 let data = [
284 f64::NAN,
285 4.2,
286 0.0,
287 f64::NEG_INFINITY,
288 -0.0,
289 f64::INFINITY,
290 -f64::NAN,
291 ];
292 let exp = vec![6, 4, 3, 1, 2, 5, 0];
293 assert_eq!(data.iter().rank().collect::<Vec<_>>(), exp);
294 assert_eq!(data.into_iter().rank().collect::<Vec<_>>(), exp);
295 }
296}