statistics 0.8.0.5 → 0.9.0.0
raw patch · 14 files changed
+178/−70 lines, 14 filesdep +aesondep +deepseqdep +monad-pardep ~mwc-randomPVP ok
version bump matches the API change (PVP)
Dependencies added: aeson, deepseq, monad-par
Dependency ranges changed: mwc-random
API changes (from Hackage documentation)
+ Statistics.Function: nextHighestPowerOfTwo :: Int -> Int
+ Statistics.Resampling.Bootstrap: instance Data Estimate
+ Statistics.Resampling.Bootstrap: instance FromJSON Estimate
+ Statistics.Resampling.Bootstrap: instance NFData Estimate
+ Statistics.Resampling.Bootstrap: instance ToJSON Estimate
+ Statistics.Resampling.Bootstrap: instance Typeable Estimate
+ Statistics.Resampling.Bootstrap: scale :: Double -> Estimate -> Estimate
- Statistics.Resampling: resample :: PrimMonad m => Gen (PrimState m) -> [Estimator] -> Int -> Sample -> m [Resample]
+ Statistics.Resampling: resample :: Gen (PrimState IO) -> [Estimator] -> Int -> Sample -> IO [Resample]
Files
- Statistics/Distribution/Binomial.hs +10/−7
- Statistics/Distribution/ChiSquared.hs +6/−2
- Statistics/Distribution/Exponential.hs +6/−3
- Statistics/Distribution/Gamma.hs +9/−2
- Statistics/Distribution/Geometric.hs +5/−2
- Statistics/Distribution/Hypergeometric.hs +9/−8
- Statistics/Distribution/Normal.hs +8/−7
- Statistics/Distribution/Poisson.hs +5/−2
- Statistics/Function.hs +22/−3
- Statistics/KernelDensity.hs +1/−1
- Statistics/Resampling.hs +46/−22
- Statistics/Resampling/Bootstrap.hs +41/−4
- Statistics/Sample.hs +4/−4
- statistics.cabal +6/−3
Statistics/Distribution/Binomial.hs view
@@ -23,7 +23,6 @@ , bdProbability ) where -import Control.Exception (assert) import Data.Typeable (Typeable) import qualified Statistics.Distribution as D import Statistics.Math (choose)@@ -49,7 +48,7 @@ mean = mean --- This could be slow for bin n+-- This could be slow for big n probability :: BinomialDistribution -> Int -> Double probability (BD n p) k | k < 0 || k > n = 0@@ -77,12 +76,16 @@ variance (BD n p) = fromIntegral n * p * (1 - p) {-# INLINE variance #-} --- | Construct binomial distribution+-- | Construct binomial distribution. Number of trials must be+-- positive and probability must be in [0,1] range binomial :: Int -- ^ Number of trials. -> Double -- ^ Probability. -> BinomialDistribution-binomial n p =- assert (n > 0) .- assert (p > 0 && p < 1) $- BD n p+binomial n p + | n <= 0 = + error $ msg ++ "number of trials must be positive. Got " ++ show n+ | p < 0 || p > 1 = + error $ msg++"probability must be in [0,1] range. Got " ++ show p+ | otherwise = BD n p+ where msg = "Statistics.Distribution.Binomial.binomial: " {-# INLINE binomial #-}
Statistics/Distribution/ChiSquared.hs view
@@ -34,9 +34,13 @@ chiSquaredNDF (ChiSquared ndf) = ndf {-# INLINE chiSquaredNDF #-} --- | Construct chi-squared distribution. Number of degrees of free+-- | Construct chi-squared distribution. Number of degrees of freedom+-- must be positive. chiSquared :: Int -> ChiSquared-chiSquared x = ChiSquared x+chiSquared n+ | n <= 0 = error $ + "Statistics.Distribution.ChiSquared.chiSquared: N.D.F. must be positive. Got " ++ show n+ | otherwise = ChiSquared n {-# INLINE chiSquared #-} instance D.Distribution ChiSquared where
Statistics/Distribution/Exponential.hs view
@@ -61,14 +61,17 @@ quantile (ED l) p = -log (1 - p) / l {-# INLINE quantile #-} --- | Create exponential distribution+-- | Create an exponential distribution. exponential :: Double -- ^ λ (scale) parameter. -> ExponentialDistribution-exponential = ED+exponential l+ | l <= 0 = + error $ "Statistics.Distribution.Exponential.exponential: scale parameter must be positive. Got " ++ show l+ | otherwise = ED l {-# INLINE exponential #-} -- | Create exponential distribution from sample. No tests are made to--- check whether it really exponential+-- check whether it truly is exponential. exponentialFromSample :: Sample -> ExponentialDistribution exponentialFromSample = ED . S.mean {-# INLINE exponentialFromSample #-}
Statistics/Distribution/Gamma.hs view
@@ -35,8 +35,15 @@ , gdScale :: {-# UNPACK #-} !Double -- ^ Scale parameter, ϑ. } deriving (Eq, Read, Show, Typeable) -gammaDistr :: Double -> Double -> GammaDistribution-gammaDistr = GD+-- | Create gamma distrivution. Both shape and scale parameters must be positive.+gammaDistr :: Double -- ^ Shape parameter. /k/+ -> Double -- ^ Scale parameter, ϑ.+ -> GammaDistribution+gammaDistr k theta+ | k <= 0 = error $ msg ++ "shape must be positive. Got " ++ show k+ | theta <= 0 = error $ msg ++ "scale must be positive. Got " ++ show theta+ | otherwise = GD k theta+ where msg = "Statistics.Distribution.Gamma.gammaDistr: " {-# INLINE gammaDistr #-} instance D.Distribution GammaDistribution where
Statistics/Distribution/Geometric.hs view
@@ -51,8 +51,11 @@ -- | Create geometric distribution geometric :: Double -- ^ Success rate -> GeometricDistribution-geometric x = assert (x >= 0 && x <= 1)- GD x+geometric x+ | x < 0 || x > 1 = + error $ "Statistics.Distribution.Geometric.geometric: probability must be in [0,1] range. Got " ++ show x+ | otherwise =+ GD x {-# INLINE geometric #-} probability :: GeometricDistribution -> Int -> Double
Statistics/Distribution/Hypergeometric.hs view
@@ -27,9 +27,8 @@ , hdK ) where -import Control.Exception (assert)-import Data.Typeable (Typeable)-import Statistics.Math (choose)+import Data.Typeable (Typeable)+import Statistics.Math (choose) import qualified Statistics.Distribution as D data HypergeometricDistribution = HD {@@ -66,11 +65,13 @@ -> Int -- ^ /l/ -> Int -- ^ /k/ -> HypergeometricDistribution-hypergeometric m l k =- assert (m >= 0 && m <= l) .- assert (l > 0) .- assert (k > 0 && k <= l) $- HD m l k+hypergeometric m l k+ | not (l > 0) = error $ msg ++ "l must be positive"+ | not (m >= 0 && m <= l) = error $ msg ++ "m must lie in [0,l] range"+ | not (k > 0 && k <= l) = error $ msg ++ "k must lie in (0,l] range"+ | otherwise = HD m l k+ where+ msg = "Statistics.Distribution.Hypergeometric.hypergeometric: " {-# INLINE hypergeometric #-} -- Naive implementation
Statistics/Distribution/Normal.hs view
@@ -20,7 +20,6 @@ , standard ) where -import Control.Exception (assert) import Data.Number.Erf (erfc) import Data.Typeable (Typeable) import Statistics.Constants (m_sqrt_2, m_sqrt_2_pi)@@ -60,12 +59,14 @@ normalDistr :: Double -- ^ Mean of distribution -> Double -- ^ Variance of distribution -> NormalDistribution-normalDistr m v = assert (v > 0)- ND { mean = m- , variance = v- , ndPdfDenom = m_sqrt_2_pi * sv- , ndCdfDenom = m_sqrt_2 * sv- }+normalDistr m v+ | v <= 0 = + error $ "Statistics.Distribution.Normal.normalDistr: variance must be positive. Got " ++ show v+ | otherwise = ND { mean = m+ , variance = v+ , ndPdfDenom = m_sqrt_2_pi * sv+ , ndCdfDenom = m_sqrt_2 * sv+ } where sv = sqrt v -- | Create distribution using parameters estimated from
Statistics/Distribution/Poisson.hs view
@@ -45,9 +45,12 @@ mean = poissonLambda {-# INLINE mean #-} --- | Create po+-- | Create poisson distribution. poisson :: Double -> PoissonDistribution-poisson = PD+poisson l+ | l <= 0 = + error $ "Statistics.Distribution.Poisson.poisson: lambda must be positive. Got " ++ show l+ | otherwise = PD l {-# INLINE poisson #-} probability :: PoissonDistribution -> Int -> Double
Statistics/Function.hs view
@@ -1,8 +1,7 @@-{-# LANGUAGE Rank2Types #-}-{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE CPP, FlexibleContexts, Rank2Types #-} -- | -- Module : Statistics.Function--- Copyright : (c) 2009, 2010 Bryan O'Sullivan+-- Copyright : (c) 2009, 2010, 2011 Bryan O'Sullivan -- License : BSD3 -- -- Maintainer : bos@serpentine.com@@ -18,12 +17,16 @@ , partialSort , indexed , indices+ , nextHighestPowerOfTwo -- * Vector setup , create ) where +#include "MachDeps.h"+ import Control.Exception (assert) import Control.Monad.Primitive (PrimMonad)+import Data.Bits ((.|.), shiftR) import Data.Vector.Generic (modify, unsafeFreeze) import qualified Data.Vector.Algorithms.Intro as I import qualified Data.Vector.Generic as G@@ -74,3 +77,19 @@ M.write arr k r loop (k+1) arr {-# INLINE create #-}++-- | Efficiently compute the next highest power of two for a+-- non-negative integer. If the given value is already a power of+-- two, it is returned unchanged. If negative, zero is returned.+nextHighestPowerOfTwo :: Int -> Int+nextHighestPowerOfTwo n = o + 1+ where m = n - 1+ o = m+ .|. (m `shiftR` 1)+ .|. (m `shiftR` 2)+ .|. (m `shiftR` 4)+ .|. (m `shiftR` 8)+ .|. (m `shiftR` 16)+#if WORD_SIZE_IN_BITS == 64 + .|. (m `shiftR` 32)+#endif
Statistics/KernelDensity.hs view
@@ -115,7 +115,7 @@ gaussianKernel :: Kernel gaussianKernel f h p v = exp (-0.5 * u * u) * g where u = (v - p) / h- g = f * m_2_sqrt_pi * m_1_sqrt_2+ g = f * 0.5 * m_2_sqrt_pi * m_1_sqrt_2 -- | Kernel density estimator, providing a non-parametric way of -- estimating the PDF of a random variable.
Statistics/Resampling.hs view
@@ -1,3 +1,5 @@+{-# LANGUAGE BangPatterns #-}+ -- | -- Module : Statistics.Resampling -- Copyright : (c) 2009, 2010 Bryan O'Sullivan@@ -16,14 +18,16 @@ , resample ) where -import Control.Monad (forM_, liftM)+import Control.Concurrent (forkIO, newChan, readChan, writeChan)+import Control.Monad (forM_, liftM, replicateM_) import Control.Monad.Primitive (PrimMonad, PrimState) import Data.Vector.Algorithms.Intro (sort) import Data.Vector.Generic (unsafeFreeze)-import Data.Vector.Unboxed ((!))-import Statistics.Function (create, indexed, indices)+import Data.Word (Word32)+import GHC.Conc (numCapabilities)+import Statistics.Function (create, indices) import Statistics.Types (Estimator, Sample)-import System.Random.MWC (Gen, uniform)+import System.Random.MWC (Gen, initialize, uniform, uniformVector) import qualified Data.Vector.Unboxed as U import qualified Data.Vector.Unboxed.Mutable as MU @@ -34,34 +38,54 @@ fromResample :: U.Vector Double } deriving (Eq, Show) --- | Resample a data set repeatedly, with replacement, computing each--- estimate over the resampled data.-resample :: (PrimMonad m) => Gen (PrimState m) -> [Estimator] -> Int -> Sample -> m [Resample]+-- | /O(e*r*s)/ Resample a data set repeatedly, with replacement,+-- computing each estimate over the resampled data.+--+-- This function is expensive; it has to do work proportional to+-- /e*r*s/, where /e/ is the number of estimation functions, /r/ is+-- the number of resamples to compute, and /s/ is the number of+-- original samples.+--+-- To improve performance, this function will make use of all+-- available CPUs. At least with GHC 7.0, parallel performance seems+-- best if the parallel garbage collector is disabled (RTS option+-- @-qg@).+resample :: Gen (PrimState IO)+ -> [Estimator] -- ^ Estimation functions.+ -> Int -- ^ Number of resamples to compute.+ -> Sample -- ^ Original sample.+ -> IO [Resample] resample gen ests numResamples samples = do+ let !numSamples = U.length samples+ ixs = scanl (+) 0 $+ zipWith (+) (replicate numCapabilities q)+ (replicate r 1 ++ repeat 0)+ where (q,r) = numResamples `quotRem` numCapabilities results <- mapM (const (MU.new numResamples)) $ ests- loop 0 (zip ests results)+ done <- newChan+ forM_ (zip ixs (tail ixs)) $ \ (start,!end) -> do+ gen' <- initialize =<< (uniformVector gen 256 :: IO (U.Vector Word32))+ forkIO $ do+ let loop k ers | k >= end = writeChan done ()+ | otherwise = do+ re <- create numSamples $ \_ -> do+ r <- uniform gen'+ return (U.unsafeIndex samples (r `mod` numSamples))+ forM_ ers $ \(est,arr) ->+ MU.write arr k . est $ re+ loop (k+1) ers+ loop start (zip ests results)+ replicateM_ numCapabilities $ readChan done mapM_ sort results mapM (liftM Resample . unsafeFreeze) results- where- loop k ers | k >= numResamples = return ()- | otherwise = do- re <- create n $ \_ -> do- r <- uniform gen- return (samples ! (abs r `mod` n))- forM_ ers $ \(est,arr) ->- MU.write arr k . est $ re- loop (k+1) ers- n = U.length samples-{-# INLINE resample #-} -- | Compute a statistical estimate repeatedly over a sample, each -- time omitting a successive element. jackknife :: Estimator -> Sample -> U.Vector Double jackknife est sample = U.map f . indices $ sample where f i = est (dropAt i sample)-{-# INLINE jackknife #-}+{- INLINE jackknife #-} -- | Drop the /k/th element of a vector. dropAt :: U.Unbox e => Int -> U.Vector e -> U.Vector e-dropAt n = U.map snd . U.filter notN . indexed- where notN (i , _) = i /= n+dropAt n v = U.slice 0 n v U.++ U.slice (n+1) (U.length v - n - 1) v
Statistics/Resampling/Bootstrap.hs view
@@ -1,6 +1,8 @@+{-# LANGUAGE DeriveDataTypeable, OverloadedStrings, RecordWildCards #-}+ -- | -- Module : Statistics.Resampling.Bootstrap--- Copyright : (c) 2009 Bryan O'Sullivan+-- Copyright : (c) 2009, 2011 Bryan O'Sullivan -- License : BSD3 -- -- Maintainer : bos@serpentine.com@@ -13,11 +15,18 @@ ( Estimate(..) , bootstrapBCA+ , scale -- * References -- $references ) where +import Control.Applicative ((<$>), (<*>), empty)+import Control.DeepSeq (NFData) import Control.Exception (assert)+import Control.Monad.Par (runPar, parMap)+import Data.Aeson.Types+import Data.Data (Data)+import Data.Typeable (Typeable) import Data.Vector.Unboxed ((!)) import Statistics.Distribution (cumulative, quantile) import Statistics.Distribution.Normal@@ -38,8 +47,36 @@ -- the confidence interval). , estConfidenceLevel :: {-# UNPACK #-} !Double -- ^ Confidence level of the confidence intervals.- } deriving (Eq, Show)+ } deriving (Eq, Show, Typeable, Data) +instance NFData Estimate++instance ToJSON Estimate where+ toJSON Estimate{..} = object [+ "estPoint" .= estPoint+ , "estLowerBound" .= estLowerBound+ , "estUpperBound" .= estUpperBound+ , "estConfidenceLevel" .= estConfidenceLevel+ ]++instance FromJSON Estimate where+ parseJSON (Object v) = Estimate <$>+ v .: "estPoint" <*>+ v .: "estLowerBound" <*>+ v .: "estUpperBound" <*>+ v .: "estConfidenceLevel"+ parseJSON _ = empty++-- | Multiply the point, lower bound, and upper bound in an 'Estimate'+-- by the given value.+scale :: Double -- ^ Value to multiply by.+ -> Estimate -> Estimate+scale f e@Estimate{..} = e {+ estPoint = f * estPoint+ , estLowerBound = f * estLowerBound+ , estUpperBound = f * estUpperBound+ }+ estimate :: Double -> Double -> Double -> Double -> Estimate estimate pt lb ub cl = assert (lb <= ub) .@@ -60,9 +97,9 @@ -> [Estimator] -- ^ Estimators -> [Resample] -- ^ Resampled data -> [Estimate]-bootstrapBCA confidenceLevel sample =+bootstrapBCA confidenceLevel sample estimators resamples = assert (confidenceLevel > 0 && confidenceLevel < 1)- zipWith e+ runPar $ parMap (uncurry e) (zip estimators resamples) where e est (Resample resample) | U.length sample == 1 = estimate pt pt pt confidenceLevel
Statistics/Sample.hs view
@@ -60,6 +60,8 @@ -- Operator ^ will be overriden import Prelude hiding ((^)) +-- | Range. The difference between the largest and smallest elements+-- of a sample. range :: (G.Vector v Double) => v Double -> Double range s = hi - lo where (lo , hi) = minMax s@@ -203,11 +205,9 @@ data V = V {-# UNPACK #-} !Double {-# UNPACK #-} !Double -sqr :: Double -> Double-sqr x = x * x- robustSumVar :: (G.Vector v Double) => Double -> v Double -> Double-robustSumVar m samp = G.sum . G.map (sqr . subtract m) $ samp+robustSumVar m samp = G.sum . G.map (square . subtract m) $ samp+ where square x = x * x {-# INLINE robustSumVar #-} -- | Maximum likelihood estimate of a sample's variance. Also known
statistics.cabal view
@@ -1,5 +1,5 @@ name: statistics-version: 0.8.0.5+version: 0.9.0.0 synopsis: A library of statistical types, data, and functions description: This library provides a number of common functions and types useful@@ -26,7 +26,7 @@ bug-reports: http://bitbucket.org/bos/statistics/issues author: Bryan O'Sullivan <bos@serpentine.com> maintainer: Bryan O'Sullivan <bos@serpentine.com>-copyright: 2009, 2010 Bryan O'Sullivan+copyright: 2009, 2010, 2011 Bryan O'Sullivan category: Math, Statistics build-type: Simple cabal-version: >= 1.6@@ -58,9 +58,12 @@ other-modules: Statistics.Internal build-depends:+ aeson, base < 5,+ deepseq >= 1.1.0.2, erf,- mwc-random >= 0.8.0.3,+ monad-par >= 0.1.0.1,+ mwc-random >= 0.8.0.5, primitive >= 0.3, time, vector >= 0.7.0.0,