use crate::structure::matrix::*;
#[cfg(feature = "dataframe")]
use crate::structure::dataframe::*;
use order_stat::{kth_by};
use self::QType::*;
use crate::traits::fp::FPVector;
pub trait Statistics {
type Array;
type Value;
fn mean(&self) -> Self::Value;
fn var(&self) -> Self::Value;
fn sd(&self) -> Self::Value;
fn cov(&self) -> Self::Array;
fn cor(&self) -> Self::Array;
}
impl Statistics for Vec<f64> {
type Array = Vec<f64>;
type Value = f64;
fn mean(&self) -> f64 {
self.reduce(0f64, |x, y| x + y) / (self.len() as f64)
}
fn var(&self) -> f64 {
let mut ss = 0f64;
let mut s = 0f64;
let mut l = 0f64;
for x in self.into_iter() {
ss += x.powf(2f64);
s += *x;
l += 1f64;
}
assert_ne!(l, 1f64);
(ss / l - (s / l).powf(2f64)) * l / (l - 1f64)
}
fn sd(&self) -> f64 {
self.var().sqrt()
}
fn cov(&self) -> Vec<f64> {
unimplemented!()
}
fn cor(&self) -> Vec<f64> {
unimplemented!()
}
}
impl Statistics for Matrix {
type Array = Matrix;
type Value = Vec<f64>;
fn mean(&self) -> Vec<f64> {
let mut container: Vec<f64> = Vec::new();
let c = self.col;
for i in 0..c {
container.push(self.col(i).mean());
}
container
}
fn var(&self) -> Vec<f64> {
let mut container: Vec<f64> = Vec::new();
let c = self.col;
for i in 0..c {
container.push(self.col(i).var());
}
container
}
fn sd(&self) -> Vec<f64> {
let mut container: Vec<f64> = Vec::new();
let c = self.col;
for i in 0..c {
container.push(self.col(i).sd());
}
container
}
fn cov(&self) -> Self {
let c = self.col;
let mut m: Self = matrix(vec![0f64; c * c], c, c, self.shape);
for i in 0..c {
let m1 = self.col(i);
for j in 0..c {
let m2 = self.col(j);
m[(i, j)] = cov(&m1, &m2);
}
}
m
}
fn cor(&self) -> Self {
let c = self.col;
let mut m: Self = matrix(vec![0f64; c * c], c, c, self.shape);
for i in 0..c {
let m1 = self.col(i);
for j in 0..c {
let m2 = self.col(j);
m[(i, j)] = cor(&m1, &m2);
}
}
m
}
}
#[cfg(feature = "dataframe")]
impl Statistics for DataFrame {
type Array = Matrix;
type Value = Self;
fn mean(&self) -> Self::Value {
let mut df = DataFrame::with_header(self.headers().map(|x| x.as_str()).collect());
for k in self.headers() {
df[k] = vec![self[k].mean()];
}
df
}
fn var(&self) -> Self::Value {
let mut df = DataFrame::with_header(self.headers().map(|x| x.as_str()).collect());
for k in self.headers() {
df[k] = vec![self[k].var()];
}
df
}
fn sd(&self) -> Self::Value {
let mut df = DataFrame::with_header(self.headers().map(|x| x.as_str()).collect());
for k in self.headers() {
df[k] = vec![self[k].sd()];
}
df
}
fn cov(&self) -> Self::Array {
let m: Matrix = self.into();
m.cov()
}
fn cor(&self) -> Self::Array {
self.to_matrix().cor()
}
}
pub fn cov(v1: &Vec<f64>, v2: &Vec<f64>) -> f64 {
let mut ss = 0f64;
let mut sx = 0f64;
let mut sy = 0f64;
let mut l = 0f64;
for (x, y) in v1.into_iter().zip(v2) {
ss += x * y;
sx += *x;
sy += *y;
l += 1f64;
}
assert_ne!(l, 1f64);
(ss / l - (sx * sy) / (l.powf(2f64))) * l / (l - 1f64)
}
pub fn cor(v1: &Vec<f64>, v2: &Vec<f64>) -> f64 {
cov(v1, v2) / (v1.sd() * v2.sd())
}
pub fn lm(input: &Matrix, target: &Matrix) -> Matrix {
let mut ones = vec![1f64; input.row * input.col];
ones.extend(&input.data);
let x = matrix(ones, input.row, input.col + 1, input.shape);
&x.pseudo_inv() * target
}
pub trait OrderedStat {
type Array;
type Value;
fn median(&self) -> Self::Value;
fn quantile(&self, q: f64, qtype: QType) -> Self::Value;
fn quantiles(&self, q: Vec<f64>, qtype: QType) -> Self::Array;
}
#[derive(Debug, Copy, Clone)]
pub enum QType {
Type1,
Type2,
Type3,
Type4,
Type5,
Type6,
Type7,
Type8,
Type9,
}
impl OrderedStat for Vec<f64> {
type Array = Self;
type Value = f64;
fn median(&self) -> Self::Value {
self.quantile(0.5, Type2)
}
fn quantile(&self, q: f64, qtype: QType) -> Self::Value {
let mut m = self.clone();
quantile_mut(&mut m, q, qtype)
}
fn quantiles(&self, q: Vec<f64>, qtype: QType) -> Self::Array {
let mut v = vec![0f64; q.len()];
let mut m = self.clone();
for i in 0 .. q.len() {
v[i] = quantile_mut(&mut m, q[i], qtype);
}
v
}
}
fn quantile_mut(v: &mut [f64], q: f64, t: QType) -> f64 {
let l = v.len();
let p = 1f64 / (l as f64);
let k = (q / p) as usize;
match t {
Type1 => {
let k = if q == 0f64 {
0
} else if q - (k as f64) * p > 0f64 {
k
} else {
k - 1
};
*kth_by(v, k, |x,y| x.partial_cmp(y).unwrap())
}
Type2 => {
if q - (k as f64) * p > 0f64 {
*kth_by(v, k, |x,y| x.partial_cmp(y).unwrap())
} else if q == 0f64 {
let k = 0;
*kth_by(v, k, |x,y| x.partial_cmp(y).unwrap())
} else if q == 1f64 {
let k = l - 1;
*kth_by(v, k, |x,y| x.partial_cmp(y).unwrap())
} else {
let prev = *kth_by(v, k-1, |x,y| x.partial_cmp(y).unwrap());
let next = *kth_by(v, k, |x,y| x.partial_cmp(y).unwrap());
(prev + next) / 2f64
}
}
_ => unimplemented!()
}
}
pub fn quantile(v: &Vec<f64>, qtype: QType) -> Vec<f64> {
let q_vec = vec![0.0, 0.25, 0.5, 0.75, 1.0];
v.quantiles(q_vec, qtype)
}