[go: up one dir, main page]

average/
lib.rs

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