diff --git a/.travis.yml b/.travis.yml index c71c2f1d..01ee30e3 100644 --- a/.travis.yml +++ b/.travis.yml @@ -18,10 +18,16 @@ before_cache: | if [[ "$TRAVIS_RUST_VERSION" == nightly ]]; then RUSTFLAGS="--cfg procmacro2_semver_exempt" cargo install cargo-tarpaulin fi -script: -- cargo clean -- cargo build -- cargo test +before_script: +- rustup component add rustfmt +# As a result of https://github.com/travis-ci/travis-ci/issues/1066, we run +# everything in one large command instead of multiple commands. +# In this way, the build stops immediately if one of the commands fails. +script: | + cargo clean && + cargo fmt --all -- --check && + cargo build && + cargo test after_success: | if [[ "$TRAVIS_RUST_VERSION" == nightly ]]; then cargo tarpaulin --out Xml diff --git a/src/correlation.rs b/src/correlation.rs index ec3a1030..200bbc45 100644 --- a/src/correlation.rs +++ b/src/correlation.rs @@ -131,14 +131,15 @@ where { let observation_axis = Axis(1); let n_observations = A::from_usize(self.len_of(observation_axis)).unwrap(); - let dof = - if ddof >= n_observations { - panic!("`ddof` needs to be strictly smaller than the \ - number of observations provided for each \ - random variable!") - } else { - n_observations - ddof - }; + let dof = if ddof >= n_observations { + panic!( + "`ddof` needs to be strictly smaller than the \ + number of observations provided for each \ + random variable!" + ) + } else { + n_observations - ddof + }; let mean = self.mean_axis(observation_axis); let denoised = self - &mean.insert_axis(observation_axis); let covariance = denoised.dot(&denoised.t()); @@ -156,7 +157,9 @@ where // observation per random variable (or no observations at all) let ddof = -A::one(); let cov = self.cov(ddof); - let std = self.std_axis(observation_axis, ddof).insert_axis(observation_axis); + let std = self + .std_axis(observation_axis, ddof) + .insert_axis(observation_axis); let std_matrix = std.dot(&std.t()); // element-wise division cov / std_matrix @@ -167,10 +170,10 @@ where mod cov_tests { use super::*; use ndarray::array; + use ndarray_rand::RandomExt; use quickcheck::quickcheck; use rand; use rand::distributions::Uniform; - use ndarray_rand::RandomExt; quickcheck! { fn constant_random_variables_have_zero_covariance_matrix(value: f64) -> bool { @@ -200,10 +203,7 @@ mod cov_tests { fn test_invalid_ddof() { let n_random_variables = 3; let n_observations = 4; - let a = Array::random( - (n_random_variables, n_observations), - Uniform::new(0., 10.) - ); + let a = Array::random((n_random_variables, n_observations), Uniform::new(0., 10.)); let invalid_ddof = (n_observations as f64) + rand::random::().abs(); a.cov(invalid_ddof); } @@ -235,45 +235,36 @@ mod cov_tests { #[test] fn test_covariance_for_random_array() { let a = array![ - [ 0.72009497, 0.12568055, 0.55705966, 0.5959984 , 0.69471457], - [ 0.56717131, 0.47619486, 0.21526298, 0.88915366, 0.91971245], - [ 0.59044195, 0.10720363, 0.76573717, 0.54693675, 0.95923036], - [ 0.24102952, 0.131347, 0.11118028, 0.21451351, 0.30515539], - [ 0.26952473, 0.93079841, 0.8080893 , 0.42814155, 0.24642258] + [0.72009497, 0.12568055, 0.55705966, 0.5959984, 0.69471457], + [0.56717131, 0.47619486, 0.21526298, 0.88915366, 0.91971245], + [0.59044195, 0.10720363, 0.76573717, 0.54693675, 0.95923036], + [0.24102952, 0.131347, 0.11118028, 0.21451351, 0.30515539], + [0.26952473, 0.93079841, 0.8080893, 0.42814155, 0.24642258] ]; let numpy_covariance = array![ - [ 0.05786248, 0.02614063, 0.06446215, 0.01285105, -0.06443992], - [ 0.02614063, 0.08733569, 0.02436933, 0.01977437, -0.06715555], - [ 0.06446215, 0.02436933, 0.10052129, 0.01393589, -0.06129912], - [ 0.01285105, 0.01977437, 0.01393589, 0.00638795, -0.02355557], - [-0.06443992, -0.06715555, -0.06129912, -0.02355557, 0.09909855] + [0.05786248, 0.02614063, 0.06446215, 0.01285105, -0.06443992], + [0.02614063, 0.08733569, 0.02436933, 0.01977437, -0.06715555], + [0.06446215, 0.02436933, 0.10052129, 0.01393589, -0.06129912], + [0.01285105, 0.01977437, 0.01393589, 0.00638795, -0.02355557], + [ + -0.06443992, + -0.06715555, + -0.06129912, + -0.02355557, + 0.09909855 + ] ]; assert_eq!(a.ndim(), 2); - assert!( - a.cov(1.).all_close( - &numpy_covariance, - 1e-8 - ) - ); + assert!(a.cov(1.).all_close(&numpy_covariance, 1e-8)); } #[test] #[should_panic] // We lose precision, hence the failing assert fn test_covariance_for_badly_conditioned_array() { - let a: Array2 = array![ - [ 1e12 + 1., 1e12 - 1.], - [ 1e-6 + 1e-12, 1e-6 - 1e-12], - ]; - let expected_covariance = array![ - [2., 2e-12], [2e-12, 2e-24] - ]; - assert!( - a.cov(1.).all_close( - &expected_covariance, - 1e-24 - ) - ); + let a: Array2 = array![[1e12 + 1., 1e12 - 1.], [1e-6 + 1e-12, 1e-6 - 1e-12],]; + let expected_covariance = array![[2., 2e-12], [2e-12, 2e-24]]; + assert!(a.cov(1.).all_close(&expected_covariance, 1e-24)); } } @@ -281,9 +272,9 @@ mod cov_tests { mod pearson_correlation_tests { use super::*; use ndarray::array; + use ndarray_rand::RandomExt; use quickcheck::quickcheck; use rand::distributions::Uniform; - use ndarray_rand::RandomExt; quickcheck! { fn output_matrix_is_symmetric(bound: f64) -> bool { @@ -337,19 +328,14 @@ mod pearson_correlation_tests { [0.26979716, 0.20887228, 0.95454999, 0.96290785] ]; let numpy_corrcoeff = array![ - [ 1. , 0.38089376, 0.08122504, -0.59931623, 0.1365648 ], - [ 0.38089376, 1. , 0.80918429, -0.52615195, 0.38954398], - [ 0.08122504, 0.80918429, 1. , 0.07134906, -0.17324776], - [-0.59931623, -0.52615195, 0.07134906, 1. , -0.8743213 ], - [ 0.1365648 , 0.38954398, -0.17324776, -0.8743213 , 1. ] + [1., 0.38089376, 0.08122504, -0.59931623, 0.1365648], + [0.38089376, 1., 0.80918429, -0.52615195, 0.38954398], + [0.08122504, 0.80918429, 1., 0.07134906, -0.17324776], + [-0.59931623, -0.52615195, 0.07134906, 1., -0.8743213], + [0.1365648, 0.38954398, -0.17324776, -0.8743213, 1.] ]; assert_eq!(a.ndim(), 2); - assert!( - a.pearson_correlation().all_close( - &numpy_corrcoeff, - 1e-7 - ) - ); + assert!(a.pearson_correlation().all_close(&numpy_corrcoeff, 1e-7)); } } diff --git a/src/histogram/bins.rs b/src/histogram/bins.rs index e0c3a1ea..3a83eae9 100644 --- a/src/histogram/bins.rs +++ b/src/histogram/bins.rs @@ -33,7 +33,6 @@ pub struct Edges { } impl From> for Edges { - /// Get an `Edges` instance from a `Vec`: /// the vector will be sorted in increasing order /// using an unstable sorting algorithm and duplicates @@ -89,7 +88,7 @@ impl From> for Edges { } } -impl Index for Edges{ +impl Index for Edges { type Output = A; /// Get the `i`-th edge. @@ -182,13 +181,11 @@ impl Edges { match self.edges.binary_search(value) { Ok(i) if i == n_edges - 1 => None, Ok(i) => Some((i, i + 1)), - Err(i) => { - match i { - 0 => None, - j if j == n_edges => None, - j => Some((j - 1, j)), - } - } + Err(i) => match i { + 0 => None, + j if j == n_edges => None, + j => Some((j - 1, j)), + }, } } @@ -309,18 +306,14 @@ impl Bins { /// ); /// ``` pub fn range_of(&self, value: &A) -> Option> - where - A: Clone, + where + A: Clone, { let edges_indexes = self.edges.indices_of(value); - edges_indexes.map( - |(left, right)| { - Range { - start: self.edges[left].clone(), - end: self.edges[right].clone(), - } - } - ) + edges_indexes.map(|(left, right)| Range { + start: self.edges[left].clone(), + end: self.edges[right].clone(), + }) } /// Get the `i`-th bin. @@ -341,7 +334,7 @@ impl Bins { /// ); /// ``` pub fn index(&self, index: usize) -> Range - where + where A: Clone, { // It was not possible to implement this functionality @@ -350,7 +343,7 @@ impl Bins { // Index, in fact, forces you to return a reference. Range { start: self.edges[index].clone(), - end: self.edges[index+1].clone(), + end: self.edges[index + 1].clone(), } } } diff --git a/src/histogram/grid.rs b/src/histogram/grid.rs index 32a7161b..bfa5afc1 100644 --- a/src/histogram/grid.rs +++ b/src/histogram/grid.rs @@ -1,8 +1,8 @@ use super::bins::Bins; use super::strategies::BinsBuildingStrategy; -use std::ops::Range; use itertools::izip; -use ndarray::{ArrayBase, Data, Ix1, Ix2, Axis}; +use ndarray::{ArrayBase, Axis, Data, Ix1, Ix2}; +use std::ops::Range; /// A `Grid` is a partition of a rectangular region of an *n*-dimensional /// space—e.g. [*a*0, *b*0) × ⋯ × [*a**n*−1, @@ -72,7 +72,6 @@ pub struct Grid { } impl From>> for Grid { - /// Get a `Grid` instance from a `Vec>`. /// /// The `i`-th element in `Vec>` represents the 1-dimensional @@ -113,9 +112,14 @@ impl Grid { where S: Data, { - assert_eq!(point.len(), self.ndim(), - "Dimension mismatch: the point has {:?} dimensions, the grid \ - expected {:?} dimensions.", point.len(), self.ndim()); + assert_eq!( + point.len(), + self.ndim(), + "Dimension mismatch: the point has {:?} dimensions, the grid \ + expected {:?} dimensions.", + point.len(), + self.ndim() + ); point .iter() .zip(self.projections.iter()) @@ -132,9 +136,14 @@ impl Grid { /// **Panics** if at least one among `(i_0, ..., i_{n-1})` is out of bounds on the respective /// coordinate axis - i.e. if there exists `j` such that `i_j >= self.projections[j].len()`. pub fn index(&self, index: &[usize]) -> Vec> { - assert_eq!(index.len(), self.ndim(), - "Dimension mismatch: the index has {0:?} dimensions, the grid \ - expected {1:?} dimensions.", index.len(), self.ndim()); + assert_eq!( + index.len(), + self.ndim(), + "Dimension mismatch: the index has {0:?} dimensions, the grid \ + expected {1:?} dimensions.", + index.len(), + self.ndim() + ); izip!(&self.projections, index) .map(|(bins, &i)| bins.index(i)) .collect() @@ -164,7 +173,7 @@ where /// [`strategy`]: strategies/index.html pub fn from_array(array: &ArrayBase) -> Self where - S: Data, + S: Data, { let bin_builders = array .axis_iter(Axis(1)) diff --git a/src/histogram/histograms.rs b/src/histogram/histograms.rs index 825aadb7..9bfe2724 100644 --- a/src/histogram/histograms.rs +++ b/src/histogram/histograms.rs @@ -1,7 +1,7 @@ +use super::errors::BinNotFound; +use super::grid::Grid; use ndarray::prelude::*; use ndarray::Data; -use super::grid::Grid; -use super::errors::BinNotFound; /// Histogram data structure. pub struct Histogram { @@ -58,8 +58,8 @@ impl Histogram { Some(bin_index) => { self.counts[&*bin_index] += 1; Ok(()) - }, - None => Err(BinNotFound) + } + None => Err(BinNotFound), } } @@ -82,8 +82,8 @@ impl Histogram { /// Extension trait for `ArrayBase` providing methods to compute histograms. pub trait HistogramExt - where - S: Data, +where + S: Data, { /// Returns the [histogram](https://en.wikipedia.org/wiki/Histogram) /// for a 2-dimensional array of points `M`. @@ -145,17 +145,16 @@ pub trait HistogramExt /// # } /// ``` fn histogram(&self, grid: Grid) -> Histogram - where - A: Ord; + where + A: Ord; } impl HistogramExt for ArrayBase - where - S: Data, - A: Ord, +where + S: Data, + A: Ord, { - fn histogram(&self, grid: Grid) -> Histogram - { + fn histogram(&self, grid: Grid) -> Histogram { let mut histogram = Histogram::new(grid); for point in self.axis_iter(Axis(0)) { let _ = histogram.add_observation(&point); diff --git a/src/histogram/mod.rs b/src/histogram/mod.rs index 9176aee1..3acbf40a 100644 --- a/src/histogram/mod.rs +++ b/src/histogram/mod.rs @@ -1,10 +1,10 @@ //! Histogram functionalities. -pub use self::histograms::{Histogram, HistogramExt}; -pub use self::bins::{Edges, Bins}; +pub use self::bins::{Bins, Edges}; pub use self::grid::{Grid, GridBuilder}; +pub use self::histograms::{Histogram, HistogramExt}; -mod histograms; mod bins; -pub mod strategies; -mod grid; pub mod errors; +mod grid; +mod histograms; +pub mod strategies; diff --git a/src/histogram/strategies.rs b/src/histogram/strategies.rs index f669b35e..eeaee686 100644 --- a/src/histogram/strategies.rs +++ b/src/histogram/strategies.rs @@ -18,13 +18,12 @@ //! [`Grid`]: ../struct.Grid.html //! [`GridBuilder`]: ../struct.GridBuilder.html //! [`NumPy`]: https://docs.scipy.org/doc/numpy/reference/generated/numpy.histogram_bin_edges.html#numpy.histogram_bin_edges +use super::super::interpolate::Nearest; +use super::super::{Quantile1dExt, QuantileExt}; +use super::{Bins, Edges}; use ndarray::prelude::*; use ndarray::Data; use num_traits::{FromPrimitive, NumOps, Zero}; -use super::super::{QuantileExt, Quantile1dExt}; -use super::super::interpolate::Nearest; -use super::{Edges, Bins}; - /// A trait implemented by all strategies to build [`Bins`] /// with parameters inferred from observations. @@ -36,8 +35,7 @@ use super::{Edges, Bins}; /// [`Bins`]: ../struct.Bins.html /// [`Grid`]: ../struct.Grid.html /// [`GridBuilder`]: ../struct.GridBuilder.html -pub trait BinsBuildingStrategy -{ +pub trait BinsBuildingStrategy { type Elem: Ord; /// Given some observations in a 1-dimensional array it returns a `BinsBuildingStrategy` /// that has learned the required parameter to build a collection of [`Bins`]. @@ -45,7 +43,7 @@ pub trait BinsBuildingStrategy /// [`Bins`]: ../struct.Bins.html fn from_array(array: &ArrayBase) -> Self where - S: Data; + S: Data; /// Returns a [`Bins`] instance, built accordingly to the parameters /// inferred from observations in [`from_array`]. @@ -140,21 +138,24 @@ pub struct Auto { } impl EquiSpaced - where - T: Ord + Clone + FromPrimitive + NumOps + Zero +where + T: Ord + Clone + FromPrimitive + NumOps + Zero, { /// **Panics** if `bin_width<=0`. - fn new(bin_width: T, min: T, max: T) -> Self - { + fn new(bin_width: T, min: T, max: T) -> Self { assert!(bin_width > T::zero()); - Self { bin_width, min, max } + Self { + bin_width, + min, + max, + } } fn build(&self) -> Bins { let n_bins = self.n_bins(); let mut edges: Vec = vec![]; - for i in 0..(n_bins+1) { - let edge = self.min.clone() + T::from_usize(i).unwrap()*self.bin_width.clone(); + for i in 0..(n_bins + 1) { + let edge = self.min.clone() + T::from_usize(i).unwrap() * self.bin_width.clone(); edges.push(edge); } Bins::new(Edges::from(edges)) @@ -167,7 +168,7 @@ impl EquiSpaced max_edge = max_edge + self.bin_width.clone(); n_bins += 1; } - return n_bins + return n_bins; } fn bin_width(&self) -> T { @@ -176,15 +177,15 @@ impl EquiSpaced } impl BinsBuildingStrategy for Sqrt - where - T: Ord + Clone + FromPrimitive + NumOps + Zero +where + T: Ord + Clone + FromPrimitive + NumOps + Zero, { type Elem = T; /// **Panics** if the array is constant or if `a.len()==0`. fn from_array(a: &ArrayBase) -> Self where - S: Data + S: Data, { let n_elems = a.len(); let n_bins = (n_elems as f64).sqrt().round() as usize; @@ -205,8 +206,8 @@ impl BinsBuildingStrategy for Sqrt } impl Sqrt - where - T: Ord + Clone + FromPrimitive + NumOps + Zero +where + T: Ord + Clone + FromPrimitive + NumOps + Zero, { /// The bin width (or bin length) according to the fitted strategy. pub fn bin_width(&self) -> T { @@ -215,18 +216,18 @@ impl Sqrt } impl BinsBuildingStrategy for Rice - where - T: Ord + Clone + FromPrimitive + NumOps + Zero +where + T: Ord + Clone + FromPrimitive + NumOps + Zero, { type Elem = T; /// **Panics** if the array is constant or if `a.len()==0`. fn from_array(a: &ArrayBase) -> Self where - S: Data + S: Data, { let n_elems = a.len(); - let n_bins = (2. * (n_elems as f64).powf(1./3.)).round() as usize; + let n_bins = (2. * (n_elems as f64).powf(1. / 3.)).round() as usize; let min = a.min().unwrap().clone(); let max = a.max().unwrap().clone(); let bin_width = compute_bin_width(min.clone(), max.clone(), n_bins); @@ -244,8 +245,8 @@ impl BinsBuildingStrategy for Rice } impl Rice - where - T: Ord + Clone + FromPrimitive + NumOps + Zero +where + T: Ord + Clone + FromPrimitive + NumOps + Zero, { /// The bin width (or bin length) according to the fitted strategy. pub fn bin_width(&self) -> T { @@ -254,15 +255,15 @@ impl Rice } impl BinsBuildingStrategy for Sturges - where - T: Ord + Clone + FromPrimitive + NumOps + Zero +where + T: Ord + Clone + FromPrimitive + NumOps + Zero, { type Elem = T; /// **Panics** if the array is constant or if `a.len()==0`. fn from_array(a: &ArrayBase) -> Self where - S: Data + S: Data, { let n_elems = a.len(); let n_bins = (n_elems as f64).log2().round() as usize + 1; @@ -283,8 +284,8 @@ impl BinsBuildingStrategy for Sturges } impl Sturges - where - T: Ord + Clone + FromPrimitive + NumOps + Zero +where + T: Ord + Clone + FromPrimitive + NumOps + Zero, { /// The bin width (or bin length) according to the fitted strategy. pub fn bin_width(&self) -> T { @@ -293,15 +294,15 @@ impl Sturges } impl BinsBuildingStrategy for FreedmanDiaconis - where - T: Ord + Clone + FromPrimitive + NumOps + Zero +where + T: Ord + Clone + FromPrimitive + NumOps + Zero, { type Elem = T; /// **Panics** if `IQR==0` or if `a.len()==0`. fn from_array(a: &ArrayBase) -> Self where - S: Data + S: Data, { let n_points = a.len(); @@ -327,11 +328,10 @@ impl BinsBuildingStrategy for FreedmanDiaconis } impl FreedmanDiaconis - where - T: Ord + Clone + FromPrimitive + NumOps + Zero +where + T: Ord + Clone + FromPrimitive + NumOps + Zero, { - fn compute_bin_width(n_bins: usize, iqr: T) -> T - { + fn compute_bin_width(n_bins: usize, iqr: T) -> T { let denominator = (n_bins as f64).powf(1. / 3.); let bin_width = T::from_usize(2).unwrap() * iqr / T::from_f64(denominator).unwrap(); bin_width @@ -344,15 +344,15 @@ impl FreedmanDiaconis } impl BinsBuildingStrategy for Auto - where - T: Ord + Clone + FromPrimitive + NumOps + Zero +where + T: Ord + Clone + FromPrimitive + NumOps + Zero, { type Elem = T; /// **Panics** if `IQR==0`, the array is constant, or `a.len()==0`. fn from_array(a: &ArrayBase) -> Self where - S: Data + S: Data, { let fd_builder = FreedmanDiaconis::from_array(&a); let sturges_builder = Sturges::from_array(&a); @@ -384,8 +384,8 @@ impl BinsBuildingStrategy for Auto } impl Auto - where - T: Ord + Clone + FromPrimitive + NumOps + Zero +where + T: Ord + Clone + FromPrimitive + NumOps + Zero, { /// The bin width (or bin length) according to the fitted strategy. pub fn bin_width(&self) -> T { diff --git a/src/lib.rs b/src/lib.rs index 5d764a67..7fbcc94f 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -23,30 +23,29 @@ //! [`NumPy`]: https://docs.scipy.org/doc/numpy-1.14.1/reference/routines.statistics.html //! [`StatsBase.jl`]: https://juliastats.github.io/StatsBase.jl/latest/ - +extern crate itertools; extern crate ndarray; extern crate noisy_float; extern crate num_traits; extern crate rand; -extern crate itertools; +#[cfg(test)] +extern crate approx; #[cfg(test)] extern crate ndarray_rand; #[cfg(test)] extern crate quickcheck; -#[cfg(test)] -extern crate approx; -pub use maybe_nan::{MaybeNan, MaybeNanExt}; -pub use quantile::{interpolate, QuantileExt, Quantile1dExt}; -pub use sort::Sort1dExt; pub use correlation::CorrelationExt; pub use histogram::HistogramExt; +pub use maybe_nan::{MaybeNan, MaybeNanExt}; +pub use quantile::{interpolate, Quantile1dExt, QuantileExt}; +pub use sort::Sort1dExt; pub use summary_statistics::SummaryStatisticsExt; +mod correlation; +pub mod histogram; mod maybe_nan; mod quantile; mod sort; -mod correlation; mod summary_statistics; -pub mod histogram; diff --git a/src/maybe_nan/impl_not_none.rs b/src/maybe_nan/impl_not_none.rs index 0fdd8b4e..658aea40 100644 --- a/src/maybe_nan/impl_not_none.rs +++ b/src/maybe_nan/impl_not_none.rs @@ -2,7 +2,7 @@ use super::NotNone; use num_traits::{FromPrimitive, ToPrimitive}; use std::cmp; use std::fmt; -use std::ops::{Add, Deref, DerefMut, Div, Mul, Sub, Rem}; +use std::ops::{Add, Deref, DerefMut, Div, Mul, Rem, Sub}; impl Deref for NotNone { type Target = T; diff --git a/src/quantile.rs b/src/quantile.rs index f92cdff7..5c9b01d2 100644 --- a/src/quantile.rs +++ b/src/quantile.rs @@ -8,7 +8,7 @@ use {MaybeNan, MaybeNanExt, Sort1dExt}; pub mod interpolate { use ndarray::azip; use ndarray::prelude::*; - use num_traits::{FromPrimitive, ToPrimitive, NumOps}; + use num_traits::{FromPrimitive, NumOps, ToPrimitive}; /// Used to provide an interpolation strategy to [`quantile_axis_mut`]. /// @@ -384,8 +384,8 @@ where /// Quantile methods for 1-D arrays. pub trait Quantile1dExt - where - S: Data, +where + S: Data, { /// Return the qth quantile of the data. /// @@ -424,8 +424,8 @@ pub trait Quantile1dExt } impl Quantile1dExt for ArrayBase - where - S: Data, +where + S: Data, { fn quantile_mut(&mut self, q: f64) -> Option where @@ -440,4 +440,3 @@ impl Quantile1dExt for ArrayBase } } } - diff --git a/src/summary_statistics/means.rs b/src/summary_statistics/means.rs index 97217c23..f1059efd 100644 --- a/src/summary_statistics/means.rs +++ b/src/summary_statistics/means.rs @@ -1,8 +1,7 @@ -use ndarray::{Data, Dimension, ArrayBase}; -use num_traits::{FromPrimitive, Float, Zero}; -use std::ops::{Add, Div}; use super::SummaryStatisticsExt; - +use ndarray::{ArrayBase, Data, Dimension}; +use num_traits::{Float, FromPrimitive, Zero}; +use std::ops::{Add, Div}; impl SummaryStatisticsExt for ArrayBase where @@ -11,7 +10,7 @@ where { fn mean(&self) -> Option where - A: Clone + FromPrimitive + Add + Div + Zero + A: Clone + FromPrimitive + Add + Div + Zero, { let n_elements = self.len(); if n_elements == 0 { @@ -31,8 +30,8 @@ where } fn geometric_mean(&self) -> Option - where - A: Float + FromPrimitive, + where + A: Float + FromPrimitive, { self.map(|x| x.ln()).mean().map(|x| x.exp()) } @@ -41,10 +40,10 @@ where #[cfg(test)] mod tests { use super::SummaryStatisticsExt; - use std::f64; use approx::abs_diff_eq; - use noisy_float::types::N64; use ndarray::{array, Array1}; + use noisy_float::types::N64; + use std::f64; #[test] fn test_means_with_nan_values() { @@ -73,16 +72,14 @@ mod tests { #[test] fn test_means_with_array_of_floats() { let a: Array1 = array![ - 0.99889651, 0.0150731 , 0.28492482, 0.83819218, 0.48413156, - 0.80710412, 0.41762936, 0.22879429, 0.43997224, 0.23831807, - 0.02416466, 0.6269962 , 0.47420614, 0.56275487, 0.78995021, - 0.16060581, 0.64635041, 0.34876609, 0.78543249, 0.19938356, - 0.34429457, 0.88072369, 0.17638164, 0.60819363, 0.250392 , - 0.69912532, 0.78855523, 0.79140914, 0.85084218, 0.31839879, - 0.63381769, 0.22421048, 0.70760302, 0.99216018, 0.80199153, - 0.19239188, 0.61356023, 0.31505352, 0.06120481, 0.66417377, - 0.63608897, 0.84959691, 0.43599069, 0.77867775, 0.88267754, - 0.83003623, 0.67016118, 0.67547638, 0.65220036, 0.68043427 + 0.99889651, 0.0150731, 0.28492482, 0.83819218, 0.48413156, 0.80710412, 0.41762936, + 0.22879429, 0.43997224, 0.23831807, 0.02416466, 0.6269962, 0.47420614, 0.56275487, + 0.78995021, 0.16060581, 0.64635041, 0.34876609, 0.78543249, 0.19938356, 0.34429457, + 0.88072369, 0.17638164, 0.60819363, 0.250392, 0.69912532, 0.78855523, 0.79140914, + 0.85084218, 0.31839879, 0.63381769, 0.22421048, 0.70760302, 0.99216018, 0.80199153, + 0.19239188, 0.61356023, 0.31505352, 0.06120481, 0.66417377, 0.63608897, 0.84959691, + 0.43599069, 0.77867775, 0.88267754, 0.83003623, 0.67016118, 0.67547638, 0.65220036, + 0.68043427 ]; // Computed using NumPy let expected_mean = 0.5475494059146699; @@ -92,7 +89,15 @@ mod tests { let expected_geometric_mean = 0.4345897639796527; abs_diff_eq!(a.mean().unwrap(), expected_mean, epsilon = f64::EPSILON); - abs_diff_eq!(a.harmonic_mean().unwrap(), expected_harmonic_mean, epsilon = f64::EPSILON); - abs_diff_eq!(a.geometric_mean().unwrap(), expected_geometric_mean, epsilon = f64::EPSILON); + abs_diff_eq!( + a.harmonic_mean().unwrap(), + expected_harmonic_mean, + epsilon = f64::EPSILON + ); + abs_diff_eq!( + a.geometric_mean().unwrap(), + expected_geometric_mean, + epsilon = f64::EPSILON + ); } } diff --git a/src/summary_statistics/mod.rs b/src/summary_statistics/mod.rs index ae05e709..6aca865f 100644 --- a/src/summary_statistics/mod.rs +++ b/src/summary_statistics/mod.rs @@ -1,14 +1,14 @@ //! Summary statistics (e.g. mean, variance, etc.). use ndarray::{Data, Dimension}; -use num_traits::{FromPrimitive, Float, Zero}; +use num_traits::{Float, FromPrimitive, Zero}; use std::ops::{Add, Div}; /// Extension trait for `ArrayBase` providing methods /// to compute several summary statistics (e.g. mean, variance, etc.). pub trait SummaryStatisticsExt - where - S: Data, - D: Dimension, +where + S: Data, + D: Dimension, { /// Returns the [`arithmetic mean`] x̅ of all elements in the array: /// @@ -24,8 +24,8 @@ pub trait SummaryStatisticsExt /// /// [`arithmetic mean`]: https://en.wikipedia.org/wiki/Arithmetic_mean fn mean(&self) -> Option - where - A: Clone + FromPrimitive + Add + Div + Zero; + where + A: Clone + FromPrimitive + Add + Div + Zero; /// Returns the [`harmonic mean`] `HM(X)` of all elements in the array: /// @@ -41,8 +41,8 @@ pub trait SummaryStatisticsExt /// /// [`harmonic mean`]: https://en.wikipedia.org/wiki/Harmonic_mean fn harmonic_mean(&self) -> Option - where - A: Float + FromPrimitive; + where + A: Float + FromPrimitive; /// Returns the [`geometric mean`] `GM(X)` of all elements in the array: /// @@ -58,9 +58,8 @@ pub trait SummaryStatisticsExt /// /// [`geometric mean`]: https://en.wikipedia.org/wiki/Geometric_mean fn geometric_mean(&self) -> Option - where - A: Float + FromPrimitive; - + where + A: Float + FromPrimitive; } mod means; diff --git a/tests/quantile.rs b/tests/quantile.rs index ae85d277..66d3c64c 100644 --- a/tests/quantile.rs +++ b/tests/quantile.rs @@ -5,8 +5,7 @@ extern crate ndarray_stats; use ndarray::prelude::*; use ndarray_stats::{ interpolate::{Higher, Linear, Lower, Midpoint, Nearest}, - QuantileExt, - Quantile1dExt, + Quantile1dExt, QuantileExt, }; #[test] @@ -158,4 +157,4 @@ fn test_midpoint_overflow() { let median = a.quantile_mut::(0.5).unwrap(); let expected_median = 130; assert_eq!(median, expected_median); -} \ No newline at end of file +}