extern crate rand;
extern crate num;
use std::collections::HashMap;
use std::hash::Hash;
use num::{Float,
One,
PrimInt,
Zero};
use super::stats_ as stats;
pub fn harmonic_mean<T>(v: &[T]) -> T
where T: Float
{
let invert = |x: &T| T::one() / *x;
let sum_of_inverted = v.iter().map(invert).fold(T::zero(), |acc, elem| acc + elem);
num::cast::<usize, T>(v.len()).unwrap() / sum_of_inverted
}
pub fn geometric_mean<T>(v: &[T]) -> T
where T: Float
{
let product = v.iter().fold(T::one(), |acc, elem| acc * *elem);
let one_over_len = T::one() / num::cast(v.len()).unwrap();
product.powf(one_over_len)
}
pub fn quadratic_mean<T>(v: &[T]) -> T
where T: Float
{
let square = |x: &T| (*x).powi(2);
let sum_of_squared = v.iter().map(square).fold(T::zero(), |acc, elem| acc + elem);
(sum_of_squared / num::cast(v.len()).unwrap()).sqrt()
}
pub fn mode<T>(v: &[T]) -> Option<T>
where T: Hash + Copy + Eq
{
match v.len() {
0 => None,
1 => Some(v[0]),
_ => {
let mut counter = HashMap::new();
for x in v.iter() {
let count = counter.entry(x).or_insert(0);
*count += 1;
}
let mut max = -1;
let mut mode = None;
for (val, count) in counter.iter() {
if *count > max {
max = *count;
mode = Some(**val);
}
}
mode
}
}
}
pub fn average_deviation<T>(v: &[T], mean: Option<T>) -> T
where T: Float
{
let mean = mean.unwrap_or_else(|| stats::mean(v));
let dev = v.iter().map(|&x| (x-mean).abs()).fold(T::zero(), |acc, elem| acc + elem);
dev / num::cast(v.len()).unwrap()
}
pub fn pearson_skewness<T>(mean: T, mode: T, stdev: T) -> T
where T: Float
{
(mean - mode) / stdev
}
pub fn skewness<T>(v: &[T], mean: Option<T>, pstdev: Option<T>) -> T
where T: Float
{
let m = stats::std_moment(v, stats::Degree::Three, mean, pstdev);
let n = num::cast(v.len()).unwrap();
let skew = m / n;
let k = ( n * ( n - T::one())).sqrt()/( n - num::cast(2).unwrap());
skew * k
}
pub fn pskewness<T>(v: &[T], mean: Option<T>, pstdev: Option<T>) -> T
where T: Float
{
let m = stats::std_moment(v, stats::Degree::Three, mean, pstdev);
m / num::cast(v.len()).unwrap()
}
pub fn kurtosis<T>(v: &[T], mean: Option<T>, pstdev: Option<T>) -> T
where T: Float
{
let two = num::cast::<f32, T>(2.0).unwrap();
let three = num::cast::<f32, T>(3.0).unwrap();
let m = stats::std_moment(v, stats::Degree::Four, mean, pstdev);
let n = num::cast(v.len()).unwrap();
let q = (n - T::one())/((n-two)*(n-three));
let gamma2 = m / n;
let kurt = q * (( ( n + T::one() ) * gamma2) - ( (n-T::one()) * three ));
kurt
}
pub fn pkurtosis<T>(v: &[T], mean: Option<T>, pstdev: Option<T>) -> T
where T: Float
{
let m = stats::std_moment(v, stats::Degree::Four, mean, pstdev);
m / num::cast(v.len()).unwrap() - num::cast(3).unwrap()
}
pub fn standard_error_mean<T>(stdev: T, sample_size: T, population_size: Option<T>) -> T
where T: Float
{
let mut err = stdev / sample_size.sqrt();
if let Some(p) = population_size {
err = err * ((p - sample_size) / (p - T::one())).sqrt()
}
err
}
pub fn standard_error_skewness<T, U>(sample_size: T) -> U
where T: PrimInt, U: Float
{
(num::cast::<f32,U>(6.0).unwrap() / num::cast(sample_size).unwrap()).sqrt()
}
pub fn standard_error_kurtosis<T, U>(sample_size: T) -> U
where T: PrimInt, U: Float
{
(num::cast::<f32,U>(24.0).unwrap() / num::cast(sample_size).unwrap()).sqrt()
}
#[cfg(test)]
mod test {
use super::*;
#[test]
fn test_harmonic_mean() {
let vec = vec![0.25, 0.5, 1.0, 1.0];
assert_eq!(harmonic_mean(&vec), 0.5);
let vec = vec![0.5, 0.5, 0.5];
assert_eq!(harmonic_mean(&vec), 0.5);
let vec = vec![1.0,2.0,4.0];
assert_eq!(harmonic_mean(&vec), 12.0/7.0);
}
#[test]
fn test_geometric_mean() {
let vec = vec![1.0, 2.0, 6.125, 12.25];
assert_eq!(geometric_mean(&vec), 3.5);
}
#[test]
fn test_quadratic_mean() {
let vec = vec![-3.0, -2.0, 0.0, 2.0, 3.0];
assert_eq!(quadratic_mean(&vec), 2.280350850198276);
}
#[test]
fn test_mode() {
let vec = vec![2,4,3,5,4,6,1,1,6,4,0,0];
assert_eq!(mode(&vec), Some(4));
let vec = vec![1];
assert_eq!(mode(&vec), Some(1));
}
#[test]
fn test_average_deviation() {
let vec = vec![2.0, 2.25, 2.5, 2.5, 3.25];
assert_eq!(average_deviation(&vec, None), 0.3);
assert_eq!(average_deviation(&vec, Some(2.75)), 0.45);
}
#[test]
fn test_pearson_skewness() {
assert_eq!(pearson_skewness(2.5, 2.25, 2.5), 0.1);
assert_eq!(pearson_skewness(2.5, 5.75, 0.5), -6.5);
}
#[test]
fn test_skewness() {
let vec = vec![1.25, 1.5, 1.5, 1.75, 1.75, 2.5, 2.75, 4.5];
assert_eq!(skewness(&vec, None, None), 1.7146101353987853);
let vec = vec![1.25, 1.5, 1.5, 1.75, 1.75, 2.5, 2.75, 4.5];
assert_eq!(skewness(&vec, Some(2.25), Some(1.0)), 1.4713288161532945);
}
#[test]
fn test_pskewness() {
let vec = vec![1.25, 1.5, 1.5, 1.75, 1.75, 2.5, 2.75, 4.5];
assert_eq!(pskewness(&vec, None, None), 1.3747465025469285);
}
#[test]
fn test_kurtosis() {
let vec = vec![1.25, 1.5, 1.5, 1.75, 1.75, 2.5, 2.75, 4.5];
assert_eq!(kurtosis(&vec, None, None), 3.036788927335642);
let vec = vec![1.25, 1.5, 1.5, 1.75, 1.75, 2.5, 2.75, 4.5];
assert_eq!(kurtosis(&vec, Some(2.25), Some(1.0)), 2.3064453125);
}
#[test]
fn test_pkurtosis() {
let vec = vec![1.25, 1.5, 1.5, 1.75, 1.75, 2.5, 2.75, 4.5];
assert_eq!(pkurtosis(&vec, None, None), 0.7794232987312579);
}
#[test]
fn test_standard_error_mean() {
assert_eq!(standard_error_mean(2.0, 16.0, None), 0.5);
}
#[test]
fn test_standard_error_skewness() {
assert_eq!(standard_error_skewness::<i32, f32>(15), 0.63245553203);
}
#[test]
fn test_standard_error_kurtosis() {
assert_eq!(standard_error_kurtosis::<i32, f32>(15), 1.2649110640);
}
}