-----------------------------------------------------------------------------
-- |
-- Module      :  Numeric.Statistics.Moment
-- Copyright   :  (c) Matthew Donadio 2002
-- License     :  GPL
--
-- Maintainer  :  m.p.donadio@ieee.org
-- Stability   :  experimental
-- Portability :  portable
--
-- Simple module for computing the various moments of a list
--
-- Reference: Ross, NRiC
--
-----------------------------------------------------------------------------

module Numeric.Statistics.Moment (mean, var,
				  stddev, avgdev,
				  skew, kurtosis) where

-- TODO: does mean pass though the list twice?  once to compute the sum,
-- and the second to compute the length?

-- TODO: does var passes through the list twice, once to compute the mean of
-- the squares, and the other to compute the mean?

-- * Functions

-- | Compute the mean of a list
--
-- @Mean(X) = 1\/N sum(i=1..N) x_i @

-- We need to use Prelude.sum intead of sum because of a buglet in the
-- Data.List library that effects nhc98

mean :: (Fractional a) => [a] -> a
mean :: forall a. Fractional a => [a] -> a
mean [a]
x = forall (t :: * -> *) a. (Foldable t, Num a) => t a -> a
Prelude.sum [a]
x forall a. Fractional a => a -> a -> a
/ (forall a b. (Integral a, Num b) => a -> b
fromIntegralforall b c a. (b -> c) -> (a -> b) -> a -> c
.forall (t :: * -> *) a. Foldable t => t a -> Int
length) [a]
x

-- | Compute the variance of a list
--
-- @Var(X) = sigma^2@
--
-- @       = 1\/N-1 sum(i=1..N) (x_i-mu)^2 @

-- This is an approximation
-- var x = (mean $ map (^2) x) - mu^2
--    where mu = mean x

var :: (Fractional a) => [a] -> a
var :: forall a. Fractional a => [a] -> a
var [a]
xs = forall (t :: * -> *) a. (Foldable t, Num a) => t a -> a
Prelude.sum (forall a b. (a -> b) -> [a] -> [b]
map (\a
x -> (a
x forall a. Num a => a -> a -> a
- a
mu)forall a b. (Num a, Integral b) => a -> b -> a
^(Int
2::Int)) [a]
xs)  forall a. Fractional a => a -> a -> a
/ (a
n forall a. Num a => a -> a -> a
- a
1)
    where mu :: a
mu = forall a. Fractional a => [a] -> a
mean [a]
xs
	  n :: a
n = forall a b. (Integral a, Num b) => a -> b
fromIntegral forall a b. (a -> b) -> a -> b
$ forall (t :: * -> *) a. Foldable t => t a -> Int
length forall a b. (a -> b) -> a -> b
$ [a]
xs

-- | Compute the standard deviation of a list
--
-- @ StdDev(X) = sigma = sqrt (Var(X)) @

stddev :: (RealFloat a) => [a] -> a
stddev :: forall a. RealFloat a => [a] -> a
stddev [a]
x = forall a. Floating a => a -> a
sqrt forall a b. (a -> b) -> a -> b
$ forall a. Fractional a => [a] -> a
var [a]
x

-- | Compute the average deviation of a list
--
-- @ AvgDev(X) = 1\/N sum(i=1..N) |x_i-mu| @

avgdev :: (RealFloat a) => [a] -> a
avgdev :: forall a. RealFloat a => [a] -> a
avgdev [a]
xs = forall (t :: * -> *) a. (Foldable t, Num a) => t a -> a
Prelude.sum (forall a b. (a -> b) -> [a] -> [b]
map (\a
x -> forall a. Num a => a -> a
abs (a
x forall a. Num a => a -> a -> a
- a
mu)) [a]
xs)  forall a. Fractional a => a -> a -> a
/ a
n
    where mu :: a
mu = forall a. Fractional a => [a] -> a
mean [a]
xs
	  n :: a
n = forall a b. (Integral a, Num b) => a -> b
fromIntegral forall a b. (a -> b) -> a -> b
$ forall (t :: * -> *) a. Foldable t => t a -> Int
length forall a b. (a -> b) -> a -> b
$ [a]
xs

-- | Compute the skew of a list
--
-- @ Skew(X) = 1\/N sum(i=1..N) ((x_i-mu)\/sigma)^3 @

skew :: (RealFloat a) => [a] -> a
skew :: forall a. RealFloat a => [a] -> a
skew [a]
xs = forall (t :: * -> *) a. (Foldable t, Num a) => t a -> a
Prelude.sum (forall a b. (a -> b) -> [a] -> [b]
map (\a
x -> ((a
x forall a. Num a => a -> a -> a
- a
mu) forall a. Fractional a => a -> a -> a
/ a
sigma)forall a b. (Num a, Integral b) => a -> b -> a
^(Int
3::Int)) [a]
xs)  forall a. Fractional a => a -> a -> a
/ a
n
    where mu :: a
mu = forall a. Fractional a => [a] -> a
mean [a]
xs
	  sigma :: a
sigma = forall a. RealFloat a => [a] -> a
stddev [a]
xs
	  n :: a
n = forall a b. (Integral a, Num b) => a -> b
fromIntegral forall a b. (a -> b) -> a -> b
$ forall (t :: * -> *) a. Foldable t => t a -> Int
length forall a b. (a -> b) -> a -> b
$ [a]
xs

-- | Compute the kurtosis of a list
--
-- @ Kurt(X) = ( 1\/N sum(i=1..N) ((x_i-mu)\/sigma)^4 ) - 3@

kurtosis :: (RealFloat a) => [a] -> a
kurtosis :: forall a. RealFloat a => [a] -> a
kurtosis [a]
xs = forall (t :: * -> *) a. (Foldable t, Num a) => t a -> a
Prelude.sum (forall a b. (a -> b) -> [a] -> [b]
map (\a
x -> ((a
x forall a. Num a => a -> a -> a
- a
mu) forall a. Fractional a => a -> a -> a
/ a
sigma)forall a b. (Num a, Integral b) => a -> b -> a
^(Int
4::Int)) [a]
xs)  forall a. Fractional a => a -> a -> a
/ a
n forall a. Num a => a -> a -> a
- a
3
    where mu :: a
mu = forall a. Fractional a => [a] -> a
mean [a]
xs
	  sigma :: a
sigma = forall a. RealFloat a => [a] -> a
stddev [a]
xs
	  n :: a
n = forall a b. (Integral a, Num b) => a -> b
fromIntegral forall a b. (a -> b) -> a -> b
$ forall (t :: * -> *) a. Foldable t => t a -> Int
length forall a b. (a -> b) -> a -> b
$ [a]
xs