1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133
//! This crate provides estimators for statistics on a sequence of numbers. The //! typical workflow looks like this: //! //! 1. If necessary, build your custom estimator using [`concatenate`] or //! [`define_moments`]. //! 2. Initialize the estimator of your choice with `new()`. //! 3. Add some subset (called "sample") of the sequence of numbers (called //! "population") for which you want to estimate the statistic, using `add()` //! or `collect()`. //! 4. Calculate the statistic with `mean()` or similar. //! //! You can run several estimators in parallel and merge them into one with //! `merge()`. //! //! Everything is calculated iteratively in a single pass using constant memory, //! so the sequence of numbers can be an iterator. The used algorithms try to //! avoid numerical instabilities. //! //! If you want [Serde](https://github.com/serde-rs/serde) support, //! include `"serde1"` in your list of features. //! //! Note that deserializing does not currently check for all invalid inputs. //! For example, if you deserialize a corrupted [`Variance`] it may return //! a negative value for variance, even though that is mathematically impossible. //! In a future minor release some of these checks may be added. //! //! //! ### Example //! //! ``` //! use average::{MeanWithError, Estimate}; //! //! let mut a: MeanWithError = (1..6).map(f64::from).collect(); //! a.add(42.); //! println!("The mean is {} ± {}.", a.mean(), a.error()); //! ``` //! //! //! ## Estimators //! //! * Mean ([`Mean`]) and its error ([`MeanWithError`]). //! * Weighted mean ([`WeightedMean`]) and its error //! ([`WeightedMeanWithError`]). //! * Variance ([`Variance`]), skewness ([`Skewness`]) and kurtosis //! ([`Kurtosis`]). //! * Arbitrary higher moments ([`define_moments`]). //! * Quantiles ([`Quantile`]). //! * Minimum ([`Min`]) and maximum ([`Max`]). //! //! //! ## Estimating several statistics at once //! //! The estimators are designed to have minimal state. The recommended way to //! calculate several of them at once is to create a struct with all the //! estimators you need. You can then implement `add` for your struct by //! forwarding to the underlying estimators. Everything is inlined, so there //! should be no overhead. //! //! You can avoid the boilerplate code by using the [`concatenate`] macro. //! //! Note that calculating moments requires calculating the lower moments, so you //! only need to include the highest moment in your struct. //! //! //! ## Calculating histograms //! //! The [`define_histogram`] macro can be used to define a histogram struct that //! uses constant memory. See [`Histogram10`] (defined using //! `define_histogram!(..., 10)`) and the extension trait [`Histogram`] //! for the methods available to the generated struct. //! //! //! [`Mean`]: ./struct.Mean.html //! [`MeanWithError`]: ./type.MeanWithError.html //! [`WeightedMean`]: ./struct.WeightedMean.html //! [`WeightedMeanWithError`]: ./struct.WeightedMeanWithError.html //! [`Variance`]: ./struct.Variance.html //! [`Skewness`]: ./struct.Skewness.html //! [`Kurtosis`]: ./struct.Kurtosis.html //! [`Quantile`]: ./struct.Quantile.html //! [`Min`]: ./struct.Min.html //! [`Max`]: ./struct.Max.html //! [`concatenate`]: ./macro.concatenate.html //! [`define_moments`]: ./macro.define_moments.html //! [`define_histogram`]: ./macro.define_histogram.html //! [`Histogram10`]: ./struct.Histogram10.html //! [`Histogram`]: ./trait.Histogram.html #![cfg_attr(doc_cfg, feature(doc_cfg))] #![allow( clippy::float_cmp, clippy::suspicious_operation_groupings, )] #![no_std] #![forbid(unsafe_code)] #![forbid(missing_docs)] #![forbid(missing_debug_implementations)] #![cfg_attr(feature = "nightly", feature(const_generics, const_evaluatable_checked))] #[macro_use] mod macros; #[macro_use] mod moments; mod weighted_mean; mod minmax; #[cfg(any(feature = "std", feature = "libm"))] #[cfg_attr(doc_cfg, doc(cfg(any(feature = "std", feature = "libm"))))] mod quantile; mod traits; #[macro_use] mod histogram; #[cfg(feature = "nightly")] #[cfg_attr(doc_cfg, doc(cfg(feature = "nightly")))] pub mod histogram_const; pub use crate::moments::{Mean, Variance, MeanWithError}; #[cfg(any(feature = "std", feature = "libm"))] #[cfg_attr(doc_cfg, doc(cfg(any(feature = "std", feature = "libm"))))] pub use crate::moments::{Skewness, Kurtosis}; pub use crate::weighted_mean::{WeightedMean, WeightedMeanWithError}; pub use crate::minmax::{Min, Max}; #[cfg(any(feature = "std", feature = "libm"))] #[cfg_attr(doc_cfg, doc(cfg(any(feature = "std", feature = "libm"))))] pub use crate::quantile::Quantile; pub use crate::traits::{Estimate, Merge, Histogram}; pub use crate::histogram::{InvalidRangeError, SampleOutOfRangeError}; define_histogram!(hist, 10); pub use crate::hist::Histogram as Histogram10; define_moments!(Moments4, 4);