indxvec/
indices.rs

1use crate::Indices;
2
3impl Indices for &[usize] {
4    /// Inverts an index, eg. from sort index to ranks.
5    /// This is a symmetric operation: any even number of applications
6    /// gives the original index, odd number gives the inverted form.
7    fn invindex(self) -> Vec<usize> {
8        let n = self.len();
9        let mut index: Vec<usize> = vec![0; n];
10        for (i, &indxpos) in self.iter().enumerate() {
11            index[indxpos] = i
12        }
13        index
14    }
15
16    /// Sequentially collects items from `v`, based on sorted (partial) list of subscripts.
17    /// Maintains the order of v, simply leaving out items not represented in the list.
18    /// Is useful for efficient projections to subspaces.
19    fn select<T:Clone>(self, v: &[T]) -> Vec<T> {
20        self.iter().map(|&sub| v[sub].clone()).collect()
21    }
22
23    /// Given a complete (sort) index, extracts indicated values from `v`.
24    /// When ascending is false, collects in the reverse order.  
25    /// Used by msort for ascending or descending sort.   
26    fn unindex<T>(self, v: &[T], ascending: bool) -> Vec<T>
27    where
28        T: Clone,
29    {
30        if ascending {
31            self.iter().map(|&i| v[i].clone()).collect()
32        } else {
33            self.iter().rev().map(|&i| v[i].clone()).collect()
34        }
35    }
36
37    /// Complement of an index  (is symmetric) -
38    /// .complindex() toggles rank index between ascending/descending.
39    /// To toggle sort index between ascending/descending, use the general reversal `revs`:
40    /// `ranks.complindex().invindex()` = ranks.invindex().revs()
41    fn complindex(self) -> Vec<usize> {
42        let n = self.len();
43        let mut index: Vec<usize> = vec![0; n];
44        for (i, &inx) in self.iter().enumerate() {
45            index[i] = n - inx - 1
46        }
47        index
48    }
49
50    /// Pearson's correlation coefficient of two `$[usize]` slices.
51    /// When the inputs are ranks, then this gives Spearman's correlation
52    /// of the original data. However, in general, any other ordinal measures
53    /// could be deployed (not just the ranks).
54    fn ucorrelation(self, v: &[usize]) -> f64 {
55        let (mut sy, mut sxy, mut sx2, mut sy2) = (0_f64, 0_f64, 0_f64, 0_f64);
56        let sx: f64 = self
57            .iter()
58            .zip(v)
59            .map(|(&ux, &uy)| {
60                let x = ux as f64;
61                let y = uy as f64;
62                sy += y;
63                sxy += x * y;
64                sx2 += x * x;
65                sy2 += y * y;
66                x
67            })
68            .sum();
69        let nf = self.len() as f64;
70        (sxy - sx / nf * sy) / ((sx2 - sx / nf * sx) * (sy2 - sy / nf * sy)).sqrt()
71    }
72
73    /// Potentially useful clone-recast of &[usize] to Vec<f64>
74    fn indx_to_f64(self) -> Vec<f64> {
75        self.iter().map(|&x| x as f64).collect()
76    }
77}