----------------------------------------------------------------------------- -- | -- 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 x = Prelude.sum x / (fromIntegral.length) 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 xs = Prelude.sum (map (\x -> (x - mu)^(2::Int)) xs) / (n - 1) where mu = mean xs n = fromIntegral $ length $ xs -- | Compute the standard deviation of a list -- -- @ StdDev(X) = sigma = sqrt (Var(X)) @ stddev :: (RealFloat a) => [a] -> a stddev x = sqrt $ var 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 xs = Prelude.sum (map (\x -> abs (x - mu)) xs) / n where mu = mean xs n = fromIntegral $ length $ 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 xs = Prelude.sum (map (\x -> ((x - mu) / sigma)^(3::Int)) xs) / n where mu = mean xs sigma = stddev xs n = fromIntegral $ length $ 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 xs = Prelude.sum (map (\x -> ((x - mu) / sigma)^(4::Int)) xs) / n - 3 where mu = mean xs sigma = stddev xs n = fromIntegral $ length $ xs