1use crate::statistics::Statistics;
4use crate::vector::Vector;
5use num_traits::{Float, FromPrimitive};
6
7pub 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}