bitbelay_statistics/lib.rs
1//! Statistical tests used within `bitbelay`.
2//!
3//! # Types of Tests
4//!
5//! * Tests related to the [Chi-squared distribution] are located in the
6//! `chi_squared` module ([link](chi_squared)).
7//! * Tests related to the correlation, such as [Pearson] and [Spearman]
8//! correlation, are located in the `correlation` module
9//! ([link](correlation)).
10//!
11//! [Chi-squared distribution]: https://en.wikipedia.org/wiki/Chi-squared_distribution
12//! [Pearson]: https://en.wikipedia.org/wiki/Pearson_correlation_coefficient
13//! [Spearman]: https://en.wikipedia.org/wiki/Spearman%27s_rank_correlation_coefficient
14
15use std::collections::BTreeMap;
16
17pub mod chi_squared;
18pub mod correlation;
19
20/// Ranks the inputs according to their [sort order](std::cmp::Ord`).
21fn rank<T: Clone + Ord>(data: &[T]) -> Vec<usize> {
22 let mut sorted = data.to_vec();
23 sorted.sort();
24
25 let mut ranks = BTreeMap::new();
26 let mut current_rank = 1usize;
27
28 for value in sorted {
29 ranks.entry(value.clone()).or_insert_with(|| {
30 let rank = current_rank;
31 current_rank += 1;
32 rank
33 });
34 }
35
36 // SAFETY: we just went through every value in `data` above, so we know every
37 // element now exists and will be retrieved within `ranks`. Thus, this will
38 // always unwrap.
39 data.iter()
40 .map(|v| *ranks.get(v).unwrap())
41 .collect::<Vec<_>>()
42}
43
44#[cfg(test)]
45mod tests {
46 use crate::rank;
47
48 #[test]
49 fn rank_works_correctly() {
50 let input = &[1, 3, 5, 2, 4, 6];
51 assert_eq!(rank(input), input);
52
53 let input = &[20, 10, 40, 30];
54 assert_eq!(rank(input), &[2, 1, 4, 3]);
55 }
56}