@@ -13,6 +13,8 @@ use crate::imp_prelude::*;
13
13
use crate :: itertools:: enumerate;
14
14
use crate :: numeric_util;
15
15
16
+ use crate :: { FoldWhile , Zip } ;
17
+
16
18
/// # Numerical Methods for Arrays
17
19
impl < A , S , D > ArrayBase < S , D >
18
20
where
@@ -111,6 +113,114 @@ where
111
113
sum
112
114
}
113
115
116
+ /// Return variance of elements in the array.
117
+ ///
118
+ /// The variance is computed using the [Welford one-pass
119
+ /// algorithm](https://www.jstor.org/stable/1266577).
120
+ ///
121
+ /// The parameter `ddof` specifies the "delta degrees of freedom". For
122
+ /// example, to calculate the population variance, use `ddof = 0`, or to
123
+ /// calculate the sample variance, use `ddof = 1`.
124
+ ///
125
+ /// The variance is defined as:
126
+ ///
127
+ /// ```text
128
+ /// 1 n
129
+ /// variance = ―――――――― ∑ (xᵢ - x̅)²
130
+ /// n - ddof i=1
131
+ /// ```
132
+ ///
133
+ /// where
134
+ ///
135
+ /// ```text
136
+ /// 1 n
137
+ /// x̅ = ― ∑ xᵢ
138
+ /// n i=1
139
+ /// ```
140
+ ///
141
+ /// and `n` is the length of the array.
142
+ ///
143
+ /// **Panics** if `ddof` is less than zero or greater than `n`
144
+ ///
145
+ /// # Example
146
+ ///
147
+ /// ```
148
+ /// use ndarray::array;
149
+ /// use approx::assert_abs_diff_eq;
150
+ ///
151
+ /// let a = array![1., -4.32, 1.14, 0.32];
152
+ /// let var = a.var(1.);
153
+ /// assert_abs_diff_eq!(var, 6.7331, epsilon = 1e-4);
154
+ /// ```
155
+ pub fn var ( & self , ddof : A ) -> A
156
+ where
157
+ A : Float + FromPrimitive ,
158
+ {
159
+ let zero = A :: from_usize ( 0 ) . expect ( "Converting 0 to `A` must not fail." ) ;
160
+ let n = A :: from_usize ( self . len ( ) ) . expect ( "Converting length to `A` must not fail." ) ;
161
+ assert ! (
162
+ !( ddof < zero || ddof > n) ,
163
+ "`ddof` must not be less than zero or greater than the length of \
164
+ the axis",
165
+ ) ;
166
+ let dof = n - ddof;
167
+ let mut mean = A :: zero ( ) ;
168
+ let mut sum_sq = A :: zero ( ) ;
169
+ for ( i, & x) in self . into_iter ( ) . enumerate ( ) {
170
+ let count = A :: from_usize ( i + 1 ) . expect ( "Converting index to `A` must not fail." ) ;
171
+ let delta = x - mean;
172
+ mean = mean + delta / count;
173
+ sum_sq = ( x - mean) . mul_add ( delta, sum_sq) ;
174
+ }
175
+ sum_sq / dof
176
+ }
177
+
178
+ /// Return standard deviation of elements in the array.
179
+ ///
180
+ /// The standard deviation is computed from the variance using
181
+ /// the [Welford one-pass algorithm](https://www.jstor.org/stable/1266577).
182
+ ///
183
+ /// The parameter `ddof` specifies the "delta degrees of freedom". For
184
+ /// example, to calculate the population standard deviation, use `ddof = 0`,
185
+ /// or to calculate the sample standard deviation, use `ddof = 1`.
186
+ ///
187
+ /// The standard deviation is defined as:
188
+ ///
189
+ /// ```text
190
+ /// ⎛ 1 n ⎞
191
+ /// stddev = sqrt ⎜ ―――――――― ∑ (xᵢ - x̅)²⎟
192
+ /// ⎝ n - ddof i=1 ⎠
193
+ /// ```
194
+ ///
195
+ /// where
196
+ ///
197
+ /// ```text
198
+ /// 1 n
199
+ /// x̅ = ― ∑ xᵢ
200
+ /// n i=1
201
+ /// ```
202
+ ///
203
+ /// and `n` is the length of the array.
204
+ ///
205
+ /// **Panics** if `ddof` is less than zero or greater than `n`
206
+ ///
207
+ /// # Example
208
+ ///
209
+ /// ```
210
+ /// use ndarray::array;
211
+ /// use approx::assert_abs_diff_eq;
212
+ ///
213
+ /// let a = array![1., -4.32, 1.14, 0.32];
214
+ /// let stddev = a.std(1.);
215
+ /// assert_abs_diff_eq!(stddev, 2.59483, epsilon = 1e-4);
216
+ /// ```
217
+ pub fn std ( & self , ddof : A ) -> A
218
+ where
219
+ A : Float + FromPrimitive ,
220
+ {
221
+ self . var ( ddof) . sqrt ( )
222
+ }
223
+
114
224
/// Return sum along `axis`.
115
225
///
116
226
/// ```
0 commit comments