Commits

John McDonnell committed ce53212

Rewrote generalized t in terms of linear transformer over distributions.

Made @Shimuuar's suggested changes.

Comments (0)

Files changed (4)

Statistics/Distribution/StudentT.hs

     StudentT
   , studentT
   , studentTndf
+  , studentTUnstandardized
   ) where
 
+
 import qualified Statistics.Distribution as D
+import Statistics.Distribution.Transform (LinearTransform (..))
 import Data.Typeable         (Typeable)
 import Numeric.SpecFunctions (logBeta, incompleteBeta, invIncompleteBeta)
 
-
-
 -- | Student-T distribution
 newtype StudentT = StudentT { studentTndf :: Double }
                    deriving (Eq,Show,Read,Typeable)
 
-
 -- | Create Student-T distribution. Number of parameters must be positive.
 studentT :: Double -> StudentT
 studentT ndf
 
 instance D.ContGen StudentT where
   genContVar = D.genContinous
+
+-- | Create an unstandardized Student-t distribution
+studentTUnstandardized :: Double -> Double -> Double -> LinearTransform StudentT
+studentTUnstandardized ndf mu sigma
+  | sigma <= 0 = error $ "Statistics.Distribution.StudentT.studentTGeneral: sigma must be > 0. Got: " ++ (show sigma)
+  | otherwise = LinearTransform mu sigma (StudentT ndf)
+

Statistics/Distribution/Transform.hs

+{-# LANGUAGE FlexibleInstances, UndecidableInstances, FlexibleContexts, DeriveDataTypeable #-}
+-- |
+-- Module    : Statistics.Distribution.Transform
+-- Copyright : (c) 2013 John McDonnell;
+-- License   : BSD3
+--
+-- Maintainer  : bos@serpentine.com
+-- Stability   : experimental
+-- Portability : portable
+--
+-- Transformations over distributions
+
+module Statistics.Distribution.Transform (
+    LinearTransform (..)
+  ) where
+
+import qualified Statistics.Distribution as D
+import Data.Typeable         (Typeable)
+
+data LinearTransform d = LinearTransform
+  { location :: {-# UNPACK #-} !Double
+  , scale :: {-# UNPACK #-} !Double
+  , distr :: d
+  } deriving (Eq,Show,Read,Typeable)
+
+instance Functor LinearTransform where
+  fmap f (LinearTransform loc sc dist) = LinearTransform loc sc (f dist)
+
+instance D.Distribution d => D.Distribution (LinearTransform d) where
+  cumulative (LinearTransform loc sc dist) x = D.cumulative dist ((x-loc)/sc)
+
+instance D.ContDistr d => D.ContDistr (LinearTransform d) where
+  density (LinearTransform loc sc dist) x = (/sc) $ D.density dist ((x-loc)/sc)
+  quantile (LinearTransform loc sc dist) p = loc + sc * D.quantile dist p 
+
+instance D.MaybeMean d => D.MaybeMean (LinearTransform d) where
+  maybeMean (LinearTransform loc _ dist) = fmap (+loc) (D.maybeMean dist)
+
+instance (D.Mean d) => D.Mean (LinearTransform d) where
+  mean (LinearTransform loc _ dist) = loc + (D.mean dist)
+
+instance D.MaybeVariance  d => D.MaybeVariance (LinearTransform d) where
+  maybeVariance (LinearTransform _ sc dist) = fmap ((*sc).(*sc)) (D.maybeVariance dist)
+  maybeStdDev (LinearTransform _ sc dist) = fmap (*sc) (D.maybeStdDev dist)
+
+instance (D.Variance d) => D.Variance (LinearTransform d) where
+  variance (LinearTransform _ sc dist) = sc * sc * (D.variance dist)
+  stdDev (LinearTransform _ sc dist) = sc * (D.stdDev dist)
+
+instance D.ContDistr d => D.ContGen (LinearTransform d) where
+  genContVar = D.genContinous
+
     Statistics.Distribution.Normal
     Statistics.Distribution.Poisson
     Statistics.Distribution.StudentT
+    Statistics.Distribution.Transform
     Statistics.Distribution.Uniform
     Statistics.Function
     Statistics.Math

tests/Tests/Distribution.hs

 import Statistics.Distribution.Normal
 import Statistics.Distribution.Poisson
 import Statistics.Distribution.StudentT
+import Statistics.Distribution.Transform
 import Statistics.Distribution.Uniform
 
 import Prelude hiding (catch)
   , contDistrTests (T :: T NormalDistribution      )
   , contDistrTests (T :: T UniformDistribution     )
   , contDistrTests (T :: T StudentT                )
+  , contDistrTests (T :: T (LinearTransform StudentT) )
   , contDistrTests (T :: T FDistribution           )
 
   , discreteDistrTests (T :: T BinomialDistribution       )
                 <*> ((abs <$> arbitrary) `suchThat` (> 0))
 instance QC.Arbitrary StudentT where
   arbitrary = studentT <$> ((abs <$> arbitrary) `suchThat` (>0))
+instance QC.Arbitrary (LinearTransform StudentT) where
+  arbitrary = studentTUnstandardized
+           <$> ((abs <$> arbitrary) `suchThat` (>0))
+           <*> ((abs <$> arbitrary))
+           <*> ((abs <$> arbitrary) `suchThat` (>0))
 instance QC.Arbitrary FDistribution where
   arbitrary =  fDistribution 
            <$> ((abs <$> arbitrary) `suchThat` (>0))
   invQuantilePrec _ = 1e-13
   okForInfLimit   d = studentTndf d > 0.75
 
+instance Param (LinearTransform StudentT) where
+  invQuantilePrec _ = 1e-13
+  okForInfLimit   d = (studentTndf . distr) d > 0.75
+
 instance Param FDistribution where
   invQuantilePrec _ = 1e-12
 
   , testStudentCDF 0.3  3.34  0.757146   -- CDF
   , testStudentCDF 1    0.42  0.626569
   , testStudentCDF 4.4  0.33  0.621739
+    -- Student-T General
+  , testStudentUnstandardizedPDF 0.3    1.2  4      0.45 0.0533456  -- PDF
+  , testStudentUnstandardizedPDF 4.3  (-2.4) 3.22 (-0.6) 0.0971141
+  , testStudentUnstandardizedPDF 3.8    0.22 7.62   0.14 0.0490523
+  , testStudentUnstandardizedCDF 0.3    1.2  4      0.45 0.458035   -- CDF
+  , testStudentUnstandardizedCDF 4.3  (-2.4) 3.22 (-0.6) 0.698001
+  , testStudentUnstandardizedCDF 3.8    0.22 7.62   0.14 0.496076
     -- F-distribution
   , testFdistrPDF  1  3   3     (1/(6 * pi)) -- PDF
   , testFdistrPDF  2  2   1.2   0.206612
     testStudentCDF ndf x exact
       = testAssertion (printf "cumulative (studentT %f) %f ~ %f" ndf x exact)
       $ eq 1e-5  exact  (cumulative (studentT ndf) x)
+    -- Student-T General
+    testStudentUnstandardizedPDF ndf mu sigma x exact
+      = testAssertion (printf "density (studentTUnstandardized %f %f %f) %f ~ %f" ndf mu sigma x exact)
+      $ eq 1e-5  exact  (density (studentTUnstandardized ndf mu sigma) x)
+    testStudentUnstandardizedCDF ndf mu sigma x exact
+      = testAssertion (printf "cumulative (studentTUnstandardized %f %f %f) %f ~ %f" ndf mu sigma x exact)
+      $ eq 1e-5  exact  (cumulative (studentTUnstandardized ndf mu sigma) x)
     -- F-distribution
     testFdistrPDF n m x exact
       = testAssertion (printf "density (fDistribution %i %i) %f ~ %f [got %f]" n m x exact d)