math_ops/
normalize.rs

1//! Normalization methods for `Vector<T>`.
2
3use crate::statistics::Statistics;
4use crate::vector::Vector;
5use num_traits::{Float, FromPrimitive};
6
7/// Trait providing normalization methods for `Vector<T>`.
8pub trait Normalize<T> {
9  fn min_max_normalize(&self) -> Vector<T>;
10  fn standardize(&self) -> Vector<T>;
11}
12
13impl<T> Normalize<T> for Vector<T>
14where
15  T: Float + FromPrimitive + Copy + PartialOrd,
16{
17  fn min_max_normalize(&self) -> Vector<T> {
18    let non_nan_values: Vec<&T> = self.iter().filter(|&&x| !x.is_nan()).collect();
19    if non_nan_values.is_empty() {
20      return Vector::new(vec![T::zero(); self.len()]);
21    }
22    let min = **non_nan_values.iter().min_by(|a, b| a.partial_cmp(b).unwrap()).unwrap();
23    let max = **non_nan_values.iter().max_by(|a, b| a.partial_cmp(b).unwrap()).unwrap();
24    let range = max - min;
25    if range == T::zero() {
26      return Vector::new(vec![T::zero(); self.len()]);
27    }
28    let normalized = self
29      .iter()
30      .map(|&x| {
31        if x.is_nan() {
32          T::zero()
33        } else {
34          (x - min) / range
35        }
36      })
37      .collect();
38    Vector::new(normalized)
39  }
40
41  fn standardize(&self) -> Vector<T> {
42    let mean = self.mean().unwrap_or(T::zero());
43    let stddev = self.stddev().unwrap_or(T::one());
44    if stddev == T::zero() {
45      return Vector::new(vec![T::zero(); self.len()]);
46    }
47    let standardized = self
48      .iter()
49      .map(|&x| {
50        if x.is_nan() {
51          T::zero()
52        } else {
53          (x - mean) / stddev
54        }
55      })
56      .collect();
57    Vector::new(standardized)
58  }
59}