r2rs_stats/traits/data_set.rs
1// "Whatever you do, work at it with all your heart, as working for the Lord,
2// not for human masters, since you know that you will receive an inheritance
3// from the Lord as a reward. It is the Lord Christ you are serving."
4// (Col 3:23-24)
5
6use std::{f64, fmt::Debug, iter::Sum};
7
8use num_traits::{Float, FromPrimitive, NumAssign};
9use r2rs_base::traits::StatisticalSlice;
10
11pub enum DeviationType {
12 Mean(Option<f64>),
13 Median(Option<f64>),
14 Other(f64),
15}
16
17pub trait StatArray<X> {
18 /// Maxima and Minima
19 ///
20 /// ## Description:
21 ///
22 /// Returns the (regular or *p*arallel) maxima and minima of the input
23 /// values.
24 ///
25 /// ‘pmax*()’ and ‘pmin*()’ take one or more vectors as arguments,
26 /// recycle them to common length and return a single vector giving
27 /// the _‘parallel’_ maxima (or minima) of the argument vectors.
28 ///
29 /// ## Usage:
30 ///
31 /// max(..., na.rm = FALSE)
32 /// min(..., na.rm = FALSE)
33 ///
34 /// pmax(..., na.rm = FALSE)
35 /// pmin(..., na.rm = FALSE)
36 ///
37 /// pmax.int(..., na.rm = FALSE)
38 /// pmin.int(..., na.rm = FALSE)
39 ///
40 /// ## Arguments:
41 ///
42 /// * ...: numeric or character arguments (see Note).
43 /// * na.rm: a logical indicating whether missing values should be
44 /// removed.
45 ///
46 /// ## Details:
47 ///
48 /// ‘max’ and ‘min’ return the maximum or minimum of _all_ the values
49 /// present in their arguments, as ‘integer’ if all are ‘logical’ or
50 /// ‘integer’, as ‘double’ if all are numeric, and character
51 /// otherwise.
52 ///
53 /// If ‘na.rm’ is ‘FALSE’ an ‘NA’ value in any of the arguments will
54 /// cause a value of ‘NA’ to be returned, otherwise ‘NA’ values are
55 /// ignored.
56 ///
57 /// The minimum and maximum of a numeric empty set are ‘+Inf’ and
58 /// ‘-Inf’ (in this order!) which ensures _transitivity_, e.g.,
59 /// ‘min(x1, min(x2)) == min(x1, x2)’. For numeric ‘x’ ‘max(x) ==/
60 /// -Inf’ and ‘min(x) == +Inf’ whenever ‘length(x) == 0’ (after
61 /// removing missing values if requested). However, ‘pmax’ and ‘pmin’
62 /// return ‘NA’ if all the parallel elements are ‘NA’ even for ‘na.rm
63 /// = TRUE’.
64 ///
65 /// ‘pmax’ and ‘pmin’ take one or more vectors (or matrices) as
66 /// arguments and return a single vector giving the ‘parallel’ maxima
67 /// (or minima) of the vectors. The first element of the result is
68 /// the maximum (minimum) of the first elements of all the arguments,
69 /// the second element of the result is the maximum (minimum) of the
70 /// second elements of all the arguments and so on. Shorter inputs
71 /// (of non-zero length) are recycled if necessary. Attributes (see
72 /// ‘attributes’: such as ‘names’ or ‘dim’) are copied from the first
73 /// argument (if applicable, e.g., _not_ for an ‘S4’ object).
74 ///
75 /// ‘pmax.int’ and ‘pmin.int’ are faster internal versions only used
76 /// when all arguments are atomic vectors and there are no classes:
77 /// they drop all attributes. (Note that all versions fail for raw
78 /// and complex vectors since these have no ordering.)
79 ///
80 /// ‘max’ and ‘min’ are generic functions: methods can be defined for
81 /// them individually or via the ‘Summary’ group generic. For this to
82 /// work properly, the arguments ‘...’ should be unnamed, and dispatch
83 /// is on the first argument.
84 ///
85 /// By definition the min/max of a numeric vector containing an ‘NaN’
86 /// is ‘NaN’, except that the min/max of any vector containing an ‘NA’
87 /// is ‘NA’ even if it also contains an ‘NaN’. Note that ‘max(NA,
88 /// Inf) == NA’ even though the maximum would be ‘Inf’ whatever the
89 /// missing value actually is.
90 ///
91 /// Character versions are sorted lexicographically, and this depends
92 /// on the collating sequence of the locale in use: the help for
93 /// ‘Comparison’ gives details. The max/min of an empty character
94 /// vector is defined to be character ‘NA’. (One could argue that as
95 /// ‘""’ is the smallest character element, the maximum should be
96 /// ‘""’, but there is no obvious candidate for the minimum.)
97 ///
98 /// ## Value:
99 ///
100 /// For ‘min’ or ‘max’, a length-one vector. For ‘pmin’ or ‘pmax’, a
101 /// vector of length the longest of the input vectors, or length zero
102 /// if one of the inputs had zero length.
103 ///
104 /// The type of the result will be that of the highest of the inputs
105 /// in the hierarchy integer < double < character.
106 ///
107 /// For ‘min’ and ‘max’ if there are only numeric inputs and all are
108 /// empty (after possible removal of ‘NA’s), the result is double
109 /// (‘Inf’ or ‘-Inf’).
110 ///
111 /// ## S4 methods:
112 ///
113 /// ‘max’ and ‘min’ are part of the S4 ‘Summary’ group generic.
114 /// Methods for them must use the signature ‘x, ..., na.rm’.
115 ///
116 /// ## Note:
117 ///
118 /// ‘Numeric’ arguments are vectors of type integer and numeric, and
119 /// logical (coerced to integer). For historical reasons, ‘NULL’ is
120 /// accepted as equivalent to ‘integer(0)’.
121 ///
122 /// ‘pmax’ and ‘pmin’ will also work on classed S3 or S4 objects with
123 /// appropriate methods for comparison, ‘is.na’ and ‘rep’ (if
124 /// recycling of arguments is needed).
125 ///
126 /// ## References:
127 ///
128 /// Becker, R. A., Chambers, J. M. and Wilks, A. R. (1988) _The New S
129 /// Language_. Wadsworth & Brooks/Cole.
130 ///
131 /// ## See Also:
132 ///
133 /// ‘range’ (_both_ min and max) and ‘which.min’ (‘which.max’) for the
134 /// _arg min_, i.e., the location where an extreme value occurs.
135 ///
136 /// ‘plotmath’ for the use of ‘min’ in plot annotation.
137 ///
138 /// ## Examples:
139 ///
140 /// ```r
141 /// require(stats); require(graphics)
142 /// min(5:1, pi) #-> one number
143 /// pmin(5:1, pi) #-> 5 numbers
144 ///
145 /// x <- sort(rnorm(100)); cH <- 1.35
146 /// pmin(cH, quantile(x)) # no names
147 /// pmin(quantile(x), cH) # has names
148 /// plot(x, pmin(cH, pmax(-cH, x)), type = "b", main = "Huber's function")
149 ///
150 /// cut01 <- function(x) pmax(pmin(x, 1), 0)
151 /// curve( x^2 - 1/4, -1.4, 1.5, col = 2)
152 /// curve(cut01(x^2 - 1/4), col = "blue", add = TRUE, n = 500)
153 /// ## pmax(), pmin() preserve attributes of *first* argument
154 /// D <- diag(x = (3:1)/4) ; n0 <- numeric()
155 /// stopifnot(identical(D, cut01(D) ),
156 /// identical(n0, cut01(n0)),
157 /// identical(n0, cut01(NULL)),
158 /// identical(n0, pmax(3:1, n0, 2)),
159 /// identical(n0, pmax(n0, 4)))
160 /// ```
161 fn min(&self) -> X;
162
163 ///` Maxima and Minima
164 ///
165 /// ## Description:
166 ///
167 /// Returns the (regular or *p*arallel) maxima and minima of the input
168 /// values.
169 ///
170 /// ‘pmax*()’ and ‘pmin*()’ take one or more vectors as arguments,
171 /// recycle them to common length and return a single vector giving
172 /// the _‘parallel’_ maxima (or minima) of the argument vectors.
173 ///
174 /// ## Usage:
175 ///
176 /// max(..., na.rm = FALSE)
177 /// min(..., na.rm = FALSE)
178 ///
179 /// pmax(..., na.rm = FALSE)
180 /// pmin(..., na.rm = FALSE)
181 ///
182 /// pmax.int(..., na.rm = FALSE)
183 /// pmin.int(..., na.rm = FALSE)
184 ///
185 /// ## Arguments:
186 ///
187 /// * ...: numeric or character arguments (see Note).
188 /// * na.rm: a logical indicating whether missing values should be
189 /// removed.
190 ///
191 /// ## Details:
192 ///
193 /// ‘max’ and ‘min’ return the maximum or minimum of _all_ the values
194 /// present in their arguments, as ‘integer’ if all are ‘logical’ or
195 /// ‘integer’, as ‘double’ if all are numeric, and character
196 /// otherwise.
197 ///
198 /// If ‘na.rm’ is ‘FALSE’ an ‘NA’ value in any of the arguments will
199 /// cause a value of ‘NA’ to be returned, otherwise ‘NA’ values are
200 /// ignored.
201 ///
202 /// The minimum and maximum of a numeric empty set are ‘+Inf’ and
203 /// ‘-Inf’ (in this order!) which ensures _transitivity_, e.g.,
204 /// ‘min(x1, min(x2)) == min(x1, x2)’. For numeric ‘x’ ‘max(x) ==/
205 /// -Inf’ and ‘min(x) == +Inf’ whenever ‘length(x) == 0’ (after
206 /// removing missing values if requested). However, ‘pmax’ and ‘pmin’
207 /// return ‘NA’ if all the parallel elements are ‘NA’ even for ‘na.rm
208 /// = TRUE’.
209 ///
210 /// ‘pmax’ and ‘pmin’ take one or more vectors (or matrices) as
211 /// arguments and return a single vector giving the ‘parallel’ maxima
212 /// (or minima) of the vectors. The first element of the result is
213 /// the maximum (minimum) of the first elements of all the arguments,
214 /// the second element of the result is the maximum (minimum) of the
215 /// second elements of all the arguments and so on. Shorter inputs
216 /// (of non-zero length) are recycled if necessary. Attributes (see
217 /// ‘attributes’: such as ‘names’ or ‘dim’) are copied from the first
218 /// argument (if applicable, e.g., _not_ for an ‘S4’ object).
219 ///
220 /// ‘pmax.int’ and ‘pmin.int’ are faster internal versions only used
221 /// when all arguments are atomic vectors and there are no classes:
222 /// they drop all attributes. (Note that all versions fail for raw
223 /// and complex vectors since these have no ordering.)
224 ///
225 /// ‘max’ and ‘min’ are generic functions: methods can be defined for
226 /// them individually or via the ‘Summary’ group generic. For this to
227 /// work properly, the arguments ‘...’ should be unnamed, and dispatch
228 /// is on the first argument.
229 ///
230 /// By definition the min/max of a numeric vector containing an ‘NaN’
231 /// is ‘NaN’, except that the min/max of any vector containing an ‘NA’
232 /// is ‘NA’ even if it also contains an ‘NaN’. Note that ‘max(NA,
233 /// Inf) == NA’ even though the maximum would be ‘Inf’ whatever the
234 /// missing value actually is.
235 ///
236 /// Character versions are sorted lexicographically, and this depends
237 /// on the collating sequence of the locale in use: the help for
238 /// ‘Comparison’ gives details. The max/min of an empty character
239 /// vector is defined to be character ‘NA’. (One could argue that as
240 /// ‘""’ is the smallest character element, the maximum should be
241 /// ‘""’, but there is no obvious candidate for the minimum.)
242 ///
243 /// ## Value:
244 ///
245 /// For ‘min’ or ‘max’, a length-one vector. For ‘pmin’ or ‘pmax’, a
246 /// vector of length the longest of the input vectors, or length zero
247 /// if one of the inputs had zero length.
248 ///
249 /// The type of the result will be that of the highest of the inputs
250 /// in the hierarchy integer < double < character.
251 ///
252 /// For ‘min’ and ‘max’ if there are only numeric inputs and all are
253 /// empty (after possible removal of ‘NA’s), the result is double
254 /// (‘Inf’ or ‘-Inf’).
255 ///
256 /// ## S4 methods:
257 ///
258 /// ‘max’ and ‘min’ are part of the S4 ‘Summary’ group generic.
259 /// Methods for them must use the signature ‘x, ..., na.rm’.
260 ///
261 /// ## Note:
262 ///
263 /// ‘Numeric’ arguments are vectors of type integer and numeric, and
264 /// logical (coerced to integer). For historical reasons, ‘NULL’ is
265 /// accepted as equivalent to ‘integer(0)’.
266 ///
267 /// ‘pmax’ and ‘pmin’ will also work on classed S3 or S4 objects with
268 /// appropriate methods for comparison, ‘is.na’ and ‘rep’ (if
269 /// recycling of arguments is needed).
270 ///
271 /// ## References:
272 ///
273 /// Becker, R. A., Chambers, J. M. and Wilks, A. R. (1988) _The New S
274 /// Language_. Wadsworth & Brooks/Cole.
275 ///
276 /// ## See Also:
277 ///
278 /// ‘range’ (_both_ min and max) and ‘which.min’ (‘which.max’) for the
279 /// _arg min_, i.e., the location where an extreme value occurs.
280 ///
281 /// ‘plotmath’ for the use of ‘min’ in plot annotation.
282 ///
283 /// ## Examples:
284 ///
285 /// ```r
286 /// require(stats); require(graphics)
287 /// min(5:1, pi) #-> one number
288 /// pmin(5:1, pi) #-> 5 numbers
289 ///
290 /// x <- sort(rnorm(100)); cH <- 1.35
291 /// pmin(cH, quantile(x)) # no names
292 /// pmin(quantile(x), cH) # has names
293 /// plot(x, pmin(cH, pmax(-cH, x)), type = "b", main = "Huber's function")
294 ///
295 /// cut01 <- function(x) pmax(pmin(x, 1), 0)
296 /// curve( x^2 - 1/4, -1.4, 1.5, col = 2)
297 /// curve(cut01(x^2 - 1/4), col = "blue", add = TRUE, n = 500)
298 /// ## pmax(), pmin() preserve attributes of *first* argument
299 /// D <- diag(x = (3:1)/4) ; n0 <- numeric()
300 /// stopifnot(identical(D, cut01(D) ),
301 /// identical(n0, cut01(n0)),
302 /// identical(n0, cut01(NULL)),
303 /// identical(n0, pmax(3:1, n0, 2)),
304 /// identical(n0, pmax(n0, 4)))
305 /// ````
306 fn max(&self) -> X;
307
308 /// Sample Ranks
309 ///
310 /// ## Description:
311 ///
312 /// Returns the sample ranks of the values in a vector. Ties (i.e.,
313 /// equal values) and missing values can be handled in several ways.
314 ///
315 /// ## Usage:
316 ///
317 /// rank(x, na.last = TRUE,
318 /// ties.method = c("average", "first", "last", "random", "max", "min"))
319 ///
320 /// ## Arguments:
321 ///
322 /// * x: a numeric, complex, character or logical vector.
323 /// * na.last: a logical or character string controlling the treatment of
324 /// ‘NA’s. If ‘TRUE’, missing values in the data are put last; if
325 /// ‘FALSE’, they are put first; if ‘NA’, they are removed; if
326 /// ‘"keep"’ they are kept with rank ‘NA’.
327 /// * ties.method: a character string specifying how ties are treated, see
328 /// ‘Details’; can be abbreviated.
329 ///
330 /// ## Details:
331 ///
332 /// If all components are different (and no ‘NA’s), the ranks are well
333 /// defined, with values in ‘seq_along(x)’. With some values equal
334 /// (called ‘ties’), the argument ‘ties.method’ determines the result
335 /// at the corresponding indices. The ‘"first"’ method results in a
336 /// permutation with increasing values at each index set of ties, and
337 /// analogously ‘"last"’ with decreasing values. The ‘"random"’
338 /// method puts these in random order whereas the default,
339 /// ‘"average"’, replaces them by their mean, and ‘"max"’ and ‘"min"’
340 /// replaces them by their maximum and minimum respectively, the
341 /// latter being the typical sports ranking.
342 ///
343 /// ‘NA’ values are never considered to be equal: for ‘na.last = TRUE’
344 /// and ‘na.last = FALSE’ they are given distinct ranks in the order
345 /// in which they occur in ‘x’.
346 ///
347 /// *NB*: ‘rank’ is not itself generic but ‘xtfrm’ is, and
348 /// ‘rank(xtfrm(x), ....)’ will have the desired result if there is a
349 /// ‘xtfrm’ method. Otherwise, ‘rank’ will make use of ‘==’, ‘>’,
350 /// ‘is.na’ and extraction methods for classed objects, possibly
351 /// rather slowly.
352 ///
353 /// ## Value:
354 ///
355 /// A numeric vector of the same length as ‘x’ with names copied from
356 /// ‘x’ (unless ‘na.last = NA’, when missing values are removed). The
357 /// vector is of integer type unless ‘x’ is a long vector or
358 /// ‘ties.method = "average"’ when it is of double type (whether or
359 /// not there are any ties).
360 ///
361 /// ## References:
362 ///
363 /// Becker, R. A., Chambers, J. M. and Wilks, A. R. (1988) _The New S
364 /// Language_. Wadsworth & Brooks/Cole.
365 ///
366 /// ## See Also:
367 ///
368 /// ‘order’ and ‘sort’; ‘xtfrm’, see above.
369 ///
370 /// ## Examples:
371 ///
372 /// ```r
373 /// (r1 <- rank(x1 <- c(3, 1, 4, 15, 92)))
374 /// x2 <- c(3, 1, 4, 1, 5, 9, 2, 6, 5, 3, 5)
375 /// names(x2) <- letters[1:11]
376 /// (r2 <- rank(x2)) # ties are averaged
377 ///
378 /// ## rank() is "idempotent": rank(rank(x)) == rank(x) :
379 /// stopifnot(rank(r1) == r1, rank(r2) == r2)
380 ///
381 /// ## ranks without averaging
382 /// rank(x2, ties.method= "first") # first occurrence wins
383 /// rank(x2, ties.method= "last") # last occurrence wins
384 /// rank(x2, ties.method= "random") # ties broken at random
385 /// rank(x2, ties.method= "random") # and again
386 ///
387 /// ## keep ties ties, no average
388 /// (rma <- rank(x2, ties.method= "max")) # as used classically
389 /// (rmi <- rank(x2, ties.method= "min")) # as in Sports
390 /// stopifnot(rma + rmi == round(r2 + r2))
391 ///
392 /// ## Comparing all tie.methods:
393 /// tMeth <- eval(formals(rank)$ties.method)
394 /// rx2 <- sapply(tMeth, function(M) rank(x2, ties.method=M))
395 /// cbind(x2, rx2)
396 /// ## ties.method's does not matter w/o ties:
397 /// x <- sample(47)
398 /// rx <- sapply(tMeth, function(MM) rank(x, ties.method=MM))
399 /// stopifnot(all(rx[,1] == rx))
400 /// ```
401 fn ranks(&self) -> Vec<f64>;
402
403 /// Arithmetic Mean
404 ///
405 /// ## Description:
406 ///
407 /// Generic function for the (trimmed) arithmetic mean.
408 ///
409 /// ## Usage:
410 ///
411 /// mean(x, ...)
412 ///
413 /// ## Default S3 method:
414 /// mean(x, trim = 0, na.rm = FALSE, ...)
415 ///
416 /// ## Arguments:
417 ///
418 /// * x: An R object. Currently there are methods for numeric/logical
419 /// vectors and date, date-time and time interval objects.
420 /// Complex vectors are allowed for ‘trim = 0’, only.
421 /// * trim: the fraction (0 to 0.5) of observations to be trimmed from
422 /// each end of ‘x’ before the mean is computed. Values of trim
423 /// outside that range are taken as the nearest endpoint.
424 /// * na.rm: a logical evaluating to ‘TRUE’ or ‘FALSE’ indicating whether
425 /// ‘NA’ values should be stripped before the computation
426 /// proceeds.
427 /// * ...: further arguments passed to or from other methods.
428 ///
429 /// ## Value:
430 ///
431 /// If ‘trim’ is zero (the default), the arithmetic mean of the values
432 /// in ‘x’ is computed, as a numeric or complex vector of length one.
433 /// If ‘x’ is not logical (coerced to numeric), numeric (including
434 /// integer) or complex, ‘NA_real_’ is returned, with a warning.
435 ///
436 /// If ‘trim’ is non-zero, a symmetrically trimmed mean is computed
437 /// with a fraction of ‘trim’ observations deleted from each end
438 /// before the mean is computed.
439 ///
440 /// ## References:
441 ///
442 /// Becker, R. A., Chambers, J. M. and Wilks, A. R. (1988) _The New S
443 /// Language_. Wadsworth & Brooks/Cole.
444 ///
445 /// ## See Also:
446 ///
447 /// ‘weighted.mean’, ‘mean.POSIXct’, ‘colMeans’ for row and column
448 /// means.
449 ///
450 /// ## Examples:
451 ///
452 /// ```r
453 /// x <- c(0:10, 50)
454 /// xm <- mean(x)
455 /// c(xm, mean(x, trim = 0.10))
456 /// ```
457 fn mean(&self) -> X;
458
459 /// Median Value
460 ///
461 /// ## Description:
462 ///
463 /// Compute the sample median.
464 ///
465 /// ## Usage:
466 ///
467 /// median(x, na.rm = FALSE, ...)
468 ///
469 /// ## Arguments:
470 ///
471 /// * x: an object for which a method has been defined, or a numeric
472 /// vector containing the values whose median is to be computed.
473 /// * na.rm: a logical value indicating whether ‘NA’ values should be
474 /// stripped before the computation proceeds.
475 /// * ...: potentially further arguments for methods; not used in the
476 /// default method.
477 ///
478 /// ## Details:
479 ///
480 /// This is a generic function for which methods can be written.
481 /// However, the default method makes use of ‘is.na’, ‘sort’ and
482 /// ‘mean’ from package ‘base’ all of which are generic, and so the
483 /// default method will work for most classes (e.g., ‘"Date"’) for
484 /// which a median is a reasonable concept.
485 ///
486 /// ## Value:
487 ///
488 /// The default method returns a length-one object of the same type as
489 /// ‘x’, except when ‘x’ is logical or integer of even length, when
490 /// the result will be double.
491 ///
492 /// If there are no values or if ‘na.rm = FALSE’ and there are ‘NA’
493 /// values the result is ‘NA’ of the same type as ‘x’ (or more
494 /// generally the result of ‘x\[NA_integer_\]’).
495 ///
496 /// ## References:
497 ///
498 /// Becker, R. A., Chambers, J. M. and Wilks, A. R. (1988) _The New S
499 /// Language_. Wadsworth & Brooks/Cole.
500 ///
501 /// ## See Also:
502 ///
503 /// ‘quantile’ for general quantiles.
504 ///
505 /// ## Examples:
506 ///
507 /// ```r
508 /// median(1:4) # = 2.5 [even number]
509 /// median(c(1:3, 100, 1000)) # = 3 [odd, robust]
510 /// ```
511 fn median(&self) -> X;
512
513 /// Cumulative Sums, Products, and Extremes
514 ///
515 /// ## Description:
516 ///
517 /// Returns a vector whose elements are the cumulative sums, products,
518 /// minima or maxima of the elements of the argument.
519 ///
520 /// ## Usage:
521 ///
522 /// cumsum(x)
523 /// cumprod(x)
524 /// cummax(x)
525 /// cummin(x)
526 ///
527 /// ## Arguments:
528 ///
529 /// * x: a numeric or complex (not ‘cummin’ or ‘cummax’) object, or an
530 /// object that can be coerced to one of these.
531 ///
532 /// ## Details:
533 ///
534 /// These are generic functions: methods can be defined for them
535 /// individually or via the ‘Math’ group generic.
536 ///
537 /// ## Value:
538 ///
539 /// A vector of the same length and type as ‘x’ (after coercion),
540 /// except that ‘cumprod’ returns a numeric vector for integer input
541 /// (for consistency with ‘*’). Names are preserved.
542 ///
543 /// An ‘NA’ value in ‘x’ causes the corresponding and following
544 /// elements of the return value to be ‘NA’, as does integer overflow
545 /// in ‘cumsum’ (with a warning).
546 ///
547 /// ## S4 methods:
548 ///
549 /// ‘cumsum’ and ‘cumprod’ are S4 generic functions: methods can be
550 /// defined for them individually or via the ‘Math’ group generic.
551 /// ‘cummax’ and ‘cummin’ are individually S4 generic functions.
552 ///
553 /// ## References:
554 ///
555 /// Becker, R. A., Chambers, J. M. and Wilks, A. R. (1988) _The New S
556 /// Language_. Wadsworth & Brooks/Cole. (‘cumsum’ only.)
557 ///
558 /// ## Examples:
559 ///
560 /// ```r
561 /// cumsum(1:10)
562 /// cumprod(1:10)
563 /// cummin(c(3:1, 2:0, 4:2))
564 /// cummax(c(3:1, 2:0, 4:2))
565 /// ```
566 fn cumsum(&self) -> Vec<X>;
567 fn cumprod(&self) -> Vec<X>;
568 fn cummax(&self) -> Vec<X>;
569 fn cummin(&self) -> Vec<X>;
570
571 /// Median Absolute Deviation
572 ///
573 /// ## Description:
574 ///
575 /// Compute the median absolute deviation, i.e., the (lo-/hi-) median
576 /// of the absolute deviations from the median, and (by default)
577 /// adjust by a factor for asymptotically normal consistency.
578 ///
579 /// ## Usage:
580 ///
581 /// mad(x, center = median(x), constant = 1.4826, na.rm = FALSE,
582 /// low = FALSE, high = FALSE)
583 ///
584 /// ## Arguments:
585 ///
586 /// * x: a numeric vector.
587 /// * center: Optionally, the centre: defaults to the median.
588 /// * constant: scale factor.
589 /// * na.rm: if ‘TRUE’ then ‘NA’ values are stripped from ‘x’ before
590 /// computation takes place.
591 /// * low: if ‘TRUE’, compute the ‘lo-median’, i.e., for even sample
592 /// size, do not average the two middle values, but take the
593 /// smaller one.
594 /// * high: if ‘TRUE’, compute the ‘hi-median’, i.e., take the larger of
595 /// the two middle values for even sample size.
596 ///
597 /// ## Details:
598 ///
599 /// The actual value calculated is ‘constant * cMedian(abs(x -
600 /// center))’ with the default value of ‘center’ being ‘median(x)’,
601 /// and ‘cMedian’ being the usual, the ‘low’ or ‘high’ median, see the
602 /// arguments description for ‘low’ and ‘high’ above.
603 ///
604 /// In the case of n = 1 non-missing values and default ‘center’, the
605 /// result is ‘0’, consistent with “no deviation from the center”.
606 ///
607 /// The default ‘constant = 1.4826’ $(\text{approximately} 1/ \Phi^(-1)(3/4) = ‘1/\text{qnorm}(3/4)’)$
608 /// ensures consistency, i.e.,
609 ///
610 /// $E\[mad(X_1,...,X_n)\] = \sigma$
611 ///
612 /// for $X_i$ distributed as $N(\mu, \sigma^2)$ and large n.
613 ///
614 /// If ‘na.rm’ is ‘TRUE’ then ‘NA’ values are stripped from ‘x’ before
615 /// computation takes place. If this is not done then an ‘NA’ value
616 /// in ‘x’ will cause ‘mad’ to return ‘NA’.
617 ///
618 /// ## See Also:
619 ///
620 /// ‘IQR’ which is simpler but less robust, ‘median’, ‘var’.
621 ///
622 /// ## Examples:
623 ///
624 /// ```r
625 /// mad(c(1:9))
626 /// print(mad(c(1:9),constant = 1)) ==
627 /// mad(c(1:8, 100), constant = 1) # = 2 ; TRUE
628 /// x <- c(1,2,3,5,7,8)
629 /// sort(abs(x - median(x)))
630 /// c(mad(x, constant = 1),
631 /// mad(x, constant = 1, low = TRUE),
632 /// mad(x, constant = 1, high = TRUE))
633 /// ```
634 fn mad(&self, deviation_type: DeviationType) -> X;
635
636 fn wmad(&self, w: &Self) -> X;
637}
638
639impl<X> StatArray<X> for Vec<X>
640where
641 X: Float + Sum + NumAssign + FromPrimitive + Debug,
642{
643 fn min(&self) -> X {
644 self.as_slice().min()
645 }
646
647 fn max(&self) -> X {
648 self.as_slice().max()
649 }
650
651 fn ranks(&self) -> Vec<f64> {
652 self.as_slice().ranks()
653 }
654
655 fn mean(&self) -> X {
656 self.as_slice().mean()
657 }
658
659 fn median(&self) -> X {
660 self.as_slice().median()
661 }
662
663 fn cumsum(&self) -> Vec<X> {
664 self.as_slice().cumsum()
665 }
666 fn cumprod(&self) -> Vec<X> {
667 self.as_slice().cumprod()
668 }
669 fn cummax(&self) -> Vec<X> {
670 self.as_slice().cummax()
671 }
672 fn cummin(&self) -> Vec<X> {
673 self.as_slice().cummin()
674 }
675
676 fn mad(&self, deviation_type: DeviationType) -> X {
677 self.as_slice().mad(deviation_type)
678 }
679
680 fn wmad(&self, w: &Self) -> X {
681 self.as_slice().wmad(&w.as_slice())
682 }
683}
684
685impl<X> StatArray<X> for &[X]
686where
687 X: Float + Sum + NumAssign + FromPrimitive + Debug,
688{
689 fn min(&self) -> X {
690 *self
691 .iter()
692 .min_by(|a, b| a.partial_cmp(b).unwrap())
693 .unwrap_or(&X::nan())
694 }
695
696 fn max(&self) -> X {
697 *self
698 .iter()
699 .max_by(|a, b| a.partial_cmp(b).unwrap())
700 .unwrap_or(&X::nan())
701 }
702
703 fn ranks(&self) -> Vec<f64> {
704 let mut ret = vec![0.0; self.len()];
705 let mut sorted_x = self.iter().collect::<Vec<_>>();
706 sorted_x.sort_by(|a, b| a.partial_cmp(b).unwrap());
707
708 let mut current = 1.0;
709 for &sorted_xi in sorted_x.into_iter() {
710 let mut found = false;
711 for (pos, &xi) in self.iter().enumerate() {
712 if !found && ret[pos] == 0.0 && sorted_xi == xi {
713 ret[pos] = current;
714 current += 1.0;
715 found = true
716 }
717 }
718 }
719 ret
720 }
721
722 fn mean(&self) -> X {
723 let weight = 1.0 / self.len() as f64;
724 self.iter()
725 .map(|xi| X::from_f64(weight).unwrap() * *xi)
726 .sum()
727 }
728
729 fn median(&self) -> X {
730 if self.is_empty() {
731 X::nan()
732 } else if self.len() == 1 {
733 self[0]
734 } else {
735 let x_ranks = self.ranks();
736 let median_ranks = if (self.len()) % 2 == 0 {
737 vec![(self.len() / 2), (self.len() / 2) + 1]
738 } else {
739 vec![(self.len() / 2) + 1]
740 };
741 median_ranks
742 .iter()
743 .map(|&median_rank| {
744 self[x_ranks
745 .iter()
746 .position(|&x_rank_i| x_rank_i as usize == median_rank)
747 .unwrap()]
748 })
749 .sum::<X>()
750 / X::from_usize(median_ranks.len()).unwrap()
751 }
752 }
753
754 fn cumsum(&self) -> Vec<X> {
755 let mut accumulator = X::zero();
756 self.iter()
757 .map(|&x_i| {
758 accumulator = accumulator + x_i;
759 accumulator
760 })
761 .collect()
762 }
763
764 fn cumprod(&self) -> Vec<X> {
765 let mut accumulator = X::zero();
766 self.iter()
767 .map(|&x_i| {
768 accumulator = accumulator * x_i;
769 accumulator
770 })
771 .collect()
772 }
773
774 fn cummax(&self) -> Vec<X> {
775 let mut accumulator = X::zero();
776 self.iter()
777 .map(|&x_i| {
778 accumulator = accumulator.max(x_i);
779 accumulator
780 })
781 .collect()
782 }
783
784 fn cummin(&self) -> Vec<X> {
785 let mut accumulator = X::zero();
786 self.iter()
787 .map(|&x_i| {
788 accumulator = accumulator.min(x_i);
789 accumulator
790 })
791 .collect()
792 }
793
794 fn mad(&self, deviation_type: DeviationType) -> X {
795 let (constant, center) = match deviation_type {
796 DeviationType::Mean(center_opt) => (
797 1.253,
798 center_opt
799 .map(|c| X::from_f64(c).unwrap())
800 .unwrap_or(self.mean()),
801 ),
802 DeviationType::Median(center_opt) => (
803 1.4826,
804 center_opt
805 .map(|c| X::from_f64(c).unwrap())
806 .unwrap_or(self.median()),
807 ),
808 DeviationType::Other(center) => (1.0, X::from_f64(center).unwrap()),
809 };
810 X::from_f64(constant).unwrap()
811 * self
812 .iter()
813 .copied()
814 .map(|x_i| (x_i - center).abs())
815 .collect::<Vec<_>>()
816 .median()
817 }
818
819 fn wmad(&self, w: &Self) -> X {
820 let mut o = (0..self.len()).collect::<Vec<_>>();
821 o.sort_by(|&index1, &index2| self[index1].partial_cmp(&self[index2]).unwrap());
822
823 let x = o.iter().map(|&i| self[i].abs()).collect::<Vec<_>>();
824 let w = o.iter().map(|&i| w[i]).collect::<Vec<_>>();
825 let p = w
826 .cumsum()
827 .into_iter()
828 .map(|i| i / w.iter().cloned().sum::<X>())
829 .collect::<Vec<_>>();
830 let n = p
831 .iter()
832 .copied()
833 .filter(|&p_i| p_i < X::from_f64(0.5).unwrap())
834 .count();
835 if p[n + 1] > X::from_f64(0.5).unwrap() {
836 x[n + 1] / X::from_f64(0.6745).unwrap()
837 } else {
838 (x[n + 1] + x[n + 2]) / X::from_f64(2.0 * 0.6745).unwrap()
839 }
840 }
841}