[go: up one dir, main page]

average/moments/
mean.rs

1/// Estimate the arithmetic mean of a sequence of numbers ("population").
2///
3///
4/// ## Example
5///
6/// ```
7/// use average::Mean;
8///
9/// let a: Mean = (1..6).map(f64::from).collect();
10/// println!("The mean is {}.", a.mean());
11/// ```
12#[derive(Debug, Clone)]
13#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
14pub struct Mean {
15    /// Mean value.
16    avg: f64,
17    /// Sample size.
18    n: u64,
19}
20
21impl Mean {
22    /// Create a new mean estimator.
23    #[inline]
24    pub fn new() -> Mean {
25        Mean { avg: 0., n: 0 }
26    }
27
28    /// Increment the sample size.
29    ///
30    /// This does not update anything else.
31    #[inline]
32    fn increment(&mut self) {
33        self.n += 1;
34    }
35
36    /// Add an observation given an already calculated difference from the mean
37    /// divided by the number of samples, assuming the inner count of the sample
38    /// size was already updated.
39    ///
40    /// This is useful for avoiding unnecessary divisions in the inner loop.
41    #[inline]
42    fn add_inner(&mut self, delta_n: f64) {
43        // This algorithm introduced by Welford in 1962 trades numerical
44        // stability for a division inside the loop.
45        //
46        // See https://en.wikipedia.org/wiki/Algorithms_for_calculating_variance.
47        self.avg += delta_n;
48    }
49
50    /// Determine whether the sample is empty.
51    #[inline]
52    pub fn is_empty(&self) -> bool {
53        self.n == 0
54    }
55
56    /// Estimate the mean of the population.
57    ///
58    /// Returns NaN for an empty sample.
59    #[inline]
60    pub fn mean(&self) -> f64 {
61        if self.n > 0 { self.avg } else { f64::NAN }
62    }
63
64    /// Return the sample size.
65    #[inline]
66    pub fn len(&self) -> u64 {
67        self.n
68    }
69
70}
71
72impl core::default::Default for Mean {
73    fn default() -> Mean {
74        Mean::new()
75    }
76}
77
78impl Estimate for Mean {
79    #[inline]
80    fn add(&mut self, sample: f64) {
81        self.increment();
82        let delta_n = (sample - self.avg)
83            / self.n.to_f64().unwrap();
84        self.add_inner(delta_n);
85    }
86
87    fn estimate(&self) -> f64 {
88        self.mean()
89    }
90}
91
92impl Merge for Mean {
93    /// Merge another sample into this one.
94    ///
95    ///
96    /// ## Example
97    ///
98    /// ```
99    /// use average::{Mean, Merge};
100    ///
101    /// let sequence: &[f64] = &[1., 2., 3., 4., 5., 6., 7., 8., 9.];
102    /// let (left, right) = sequence.split_at(3);
103    /// let avg_total: Mean = sequence.iter().collect();
104    /// let mut avg_left: Mean = left.iter().collect();
105    /// let avg_right: Mean = right.iter().collect();
106    /// avg_left.merge(&avg_right);
107    /// assert_eq!(avg_total.mean(), avg_left.mean());
108    /// ```
109    #[inline]
110    fn merge(&mut self, other: &Mean) {
111        if other.is_empty() {
112            return;
113        }
114        if self.is_empty() {
115            *self = other.clone();
116            return;
117        }
118        // This algorithm was proposed by Chan et al. in 1979.
119        //
120        // See https://en.wikipedia.org/wiki/Algorithms_for_calculating_variance.
121        let len_self = self.n.to_f64().unwrap();
122        let len_other = other.n.to_f64().unwrap();
123        let len_total = len_self + len_other;
124        self.n += other.n;
125        self.avg = (len_self * self.avg + len_other * other.avg) / len_total;
126        // Chan et al. use
127        //
128        //     self.avg += delta * len_other / len_total;
129        //
130        // instead, but this results in cancellation if the number of samples are similar.
131    }
132}
133
134impl_from_iterator!(Mean);
135impl_from_par_iterator!(Mean);
136impl_extend!(Mean);