{-# LANGUAGE ViewPatterns #-}
module Statistics.Test.WilcoxonT (
wilcoxonMatchedPairTest
, wilcoxonMatchedPairSignedRank
, wilcoxonMatchedPairSignificant
, wilcoxonMatchedPairSignificance
, wilcoxonMatchedPairCriticalValue
, module Statistics.Test.Types
) where
import Data.Function (on)
import Data.List (findIndex)
import Data.Ord (comparing)
import qualified Data.Vector.Unboxed as U
import Prelude hiding (sum)
import Statistics.Function (sortBy)
import Statistics.Sample.Internal (sum)
import Statistics.Test.Internal (rank, splitByTags)
import Statistics.Test.Types
import Statistics.Types
import Statistics.Distribution
import Statistics.Distribution.Normal
wilcoxonMatchedPairSignedRank :: (Ord a, Num a, U.Unbox a) => U.Vector (a,a) -> (Int, Double, Double)
wilcoxonMatchedPairSignedRank :: forall a.
(Ord a, Num a, Unbox a) =>
Vector (a, a) -> (Int, Double, Double)
wilcoxonMatchedPairSignedRank Vector (a, a)
ab
= (Int
nRed, forall (v :: * -> *). Vector v Double => v Double -> Double
sum Vector Double
ranks1, forall a. Num a => a -> a
negate (forall (v :: * -> *). Vector v Double => v Double -> Double
sum Vector Double
ranks2))
where
(Vector Double
ranks1, Vector Double
ranks2) = forall (v :: * -> *) a.
(Vector v a, Vector v (Bool, a)) =>
v (Bool, a) -> (v a, v a)
splitByTags
forall a b. (a -> b) -> a -> b
$ forall a b.
(Unbox a, Unbox b) =>
Vector a -> Vector b -> Vector (a, b)
U.zip Vector Bool
tags (forall (v :: * -> *) a.
(Vector v a, Vector v Double) =>
(a -> a -> Bool) -> v a -> v Double
rank (forall a. Eq a => a -> a -> Bool
(==) forall b c a. (b -> b -> c) -> (a -> b) -> a -> a -> c
`on` forall a. Num a => a -> a
abs) Vector a
diffs)
diffsSorted :: Vector a
diffsSorted = forall (v :: * -> *) e. Vector v e => Comparison e -> v e -> v e
sortBy (forall a b. Ord a => (b -> a) -> b -> b -> Ordering
comparing forall a. Num a => a -> a
abs)
forall a b. (a -> b) -> a -> b
$ forall a. Unbox a => (a -> Bool) -> Vector a -> Vector a
U.filter (forall a. Eq a => a -> a -> Bool
/= a
0)
forall a b. (a -> b) -> a -> b
$ forall a b. (Unbox a, Unbox b) => (a -> b) -> Vector a -> Vector b
U.map (forall a b c. (a -> b -> c) -> (a, b) -> c
uncurry (-)) Vector (a, a)
ab
nRed :: Int
nRed = forall a. Unbox a => Vector a -> Int
U.length Vector a
diffsSorted
(Vector Bool
tags,Vector a
diffs) = forall a b.
(Unbox a, Unbox b) =>
Vector (a, b) -> (Vector a, Vector b)
U.unzip
forall a b. (a -> b) -> a -> b
$ forall a b. (Unbox a, Unbox b) => (a -> b) -> Vector a -> Vector b
U.map (\a
x -> (a
xforall a. Ord a => a -> a -> Bool
>a
0 , a
x))
forall a b. (a -> b) -> a -> b
$ Vector a
diffsSorted
coefficients :: Int -> [Integer]
coefficients :: Int -> [Integer]
coefficients Int
1 = [Integer
1, Integer
1]
coefficients Int
r = let coeffs :: [Integer]
coeffs = Int -> [Integer]
coefficients (Int
rforall a. Num a => a -> a -> a
-Int
1)
([Integer]
firstR, [Integer]
rest) = forall a. Int -> [a] -> ([a], [a])
splitAt Int
r [Integer]
coeffs
in [Integer]
firstR forall a. [a] -> [a] -> [a]
++ forall {a}. Num a => [a] -> [a] -> [a]
add [Integer]
rest [Integer]
coeffs
where
add :: [a] -> [a] -> [a]
add (a
x:[a]
xs) (a
y:[a]
ys) = a
x forall a. Num a => a -> a -> a
+ a
y forall a. a -> [a] -> [a]
: [a] -> [a] -> [a]
add [a]
xs [a]
ys
add [a]
xs [] = [a]
xs
add [] [a]
ys = [a]
ys
summedCoefficients :: Int -> [Double]
summedCoefficients :: Int -> [Double]
summedCoefficients Int
n
| Int
n forall a. Ord a => a -> a -> Bool
< Int
1 = forall a. HasCallStack => [Char] -> a
error [Char]
"Statistics.Test.WilcoxonT.summedCoefficients: nonpositive sample size"
| Int
n forall a. Ord a => a -> a -> Bool
> Int
1023 = forall a. HasCallStack => [Char] -> a
error [Char]
"Statistics.Test.WilcoxonT.summedCoefficients: sample is too large (see bug #18)"
| Bool
otherwise = forall a b. (a -> b) -> [a] -> [b]
map forall a b. (Integral a, Num b) => a -> b
fromIntegral forall a b. (a -> b) -> a -> b
$ forall a. (a -> a -> a) -> [a] -> [a]
scanl1 forall a. Num a => a -> a -> a
(+) forall a b. (a -> b) -> a -> b
$ Int -> [Integer]
coefficients Int
n
wilcoxonMatchedPairSignificant
:: PositionTest
-> PValue Double
-> (Int, Double, Double)
-> Maybe TestResult
wilcoxonMatchedPairSignificant :: PositionTest
-> PValue Double -> (Int, Double, Double) -> Maybe TestResult
wilcoxonMatchedPairSignificant PositionTest
test PValue Double
pVal (Int
sampleSize, Double
tPlus, Double
tMinus) =
case PositionTest
test of
PositionTest
AGreater -> do Int
crit <- Int -> PValue Double -> Maybe Int
wilcoxonMatchedPairCriticalValue Int
sampleSize PValue Double
pVal
forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$ Bool -> TestResult
significant forall a b. (a -> b) -> a -> b
$ forall a. Num a => a -> a
abs Double
tMinus forall a. Ord a => a -> a -> Bool
<= forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
crit
PositionTest
BGreater -> do Int
crit <- Int -> PValue Double -> Maybe Int
wilcoxonMatchedPairCriticalValue Int
sampleSize PValue Double
pVal
forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$ Bool -> TestResult
significant forall a b. (a -> b) -> a -> b
$ forall a. Num a => a -> a
abs Double
tPlus forall a. Ord a => a -> a -> Bool
<= forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
crit
PositionTest
SamplesDiffer -> do Int
crit <- Int -> PValue Double -> Maybe Int
wilcoxonMatchedPairCriticalValue Int
sampleSize (forall a. (Ord a, Num a) => a -> PValue a
mkPValue forall a b. (a -> b) -> a -> b
$ Double
pforall a. Fractional a => a -> a -> a
/Double
2)
forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$ Bool -> TestResult
significant forall a b. (a -> b) -> a -> b
$ Double
t forall a. Ord a => a -> a -> Bool
<= forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
crit
where
t :: Double
t = forall a. Ord a => a -> a -> a
min (forall a. Num a => a -> a
abs Double
tPlus) (forall a. Num a => a -> a
abs Double
tMinus)
p :: Double
p = forall a. PValue a -> a
pValue PValue Double
pVal
wilcoxonMatchedPairCriticalValue ::
Int
-> PValue Double
-> Maybe Int
wilcoxonMatchedPairCriticalValue :: Int -> PValue Double -> Maybe Int
wilcoxonMatchedPairCriticalValue Int
n PValue Double
pVal
| Int
n forall a. Ord a => a -> a -> Bool
< Int
100 =
case forall a. Num a => a -> a -> a
subtract Int
1 forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall a. (a -> Bool) -> [a] -> Maybe Int
findIndex (forall a. Ord a => a -> a -> Bool
> Double
m) (Int -> [Double]
summedCoefficients Int
n) of
Just Int
k | Int
k forall a. Ord a => a -> a -> Bool
< Int
0 -> forall a. Maybe a
Nothing
| Bool
otherwise -> forall a. a -> Maybe a
Just Int
k
Maybe Int
Nothing -> forall a. HasCallStack => [Char] -> a
error [Char]
"Statistics.Test.WilcoxonT.wilcoxonMatchedPairCriticalValue: impossible happened"
| Bool
otherwise =
case forall d. ContDistr d => d -> Double -> Double
quantile (Int -> NormalDistribution
normalApprox Int
n) Double
p of
Double
z | Double
z forall a. Ord a => a -> a -> Bool
< Double
0 -> forall a. Maybe a
Nothing
| Bool
otherwise -> forall a. a -> Maybe a
Just (forall a b. (RealFrac a, Integral b) => a -> b
round Double
z)
where
p :: Double
p = forall a. PValue a -> a
pValue PValue Double
pVal
m :: Double
m = (Double
2 forall a. Floating a => a -> a -> a
** forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
n) forall a. Num a => a -> a -> a
* Double
p
wilcoxonMatchedPairSignificance
:: Int
-> Double
-> PValue Double
wilcoxonMatchedPairSignificance :: Int -> Double -> PValue Double
wilcoxonMatchedPairSignificance Int
n Double
t
= forall a. (Ord a, Num a) => a -> PValue a
mkPValue Double
p
where
p :: Double
p | Int
n forall a. Ord a => a -> a -> Bool
< Int
100 = (Int -> [Double]
summedCoefficients Int
n forall a. [a] -> Int -> a
!! forall a b. (RealFrac a, Integral b) => a -> b
floor Double
t) forall a. Fractional a => a -> a -> a
/ Double
2 forall a. Floating a => a -> a -> a
** forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
n
| Bool
otherwise = forall d. Distribution d => d -> Double -> Double
cumulative (Int -> NormalDistribution
normalApprox Int
n) Double
t
normalApprox :: Int -> NormalDistribution
normalApprox :: Int -> NormalDistribution
normalApprox Int
ni
= Double -> Double -> NormalDistribution
normalDistr Double
m Double
s
where
m :: Double
m = Double
n forall a. Num a => a -> a -> a
* (Double
n forall a. Num a => a -> a -> a
+ Double
1) forall a. Fractional a => a -> a -> a
/ Double
4
s :: Double
s = forall a. Floating a => a -> a
sqrt forall a b. (a -> b) -> a -> b
$ (Double
n forall a. Num a => a -> a -> a
* (Double
n forall a. Num a => a -> a -> a
+ Double
1) forall a. Num a => a -> a -> a
* (Double
2forall a. Num a => a -> a -> a
*Double
n forall a. Num a => a -> a -> a
+ Double
1)) forall a. Fractional a => a -> a -> a
/ Double
24
n :: Double
n = forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
ni
wilcoxonMatchedPairTest
:: (Ord a, Num a, U.Unbox a)
=> PositionTest
-> U.Vector (a,a)
-> Test ()
wilcoxonMatchedPairTest :: forall a.
(Ord a, Num a, Unbox a) =>
PositionTest -> Vector (a, a) -> Test ()
wilcoxonMatchedPairTest PositionTest
test Vector (a, a)
pairs =
Test { testSignificance :: PValue Double
testSignificance = PValue Double
pVal
, testStatistics :: Double
testStatistics = Double
t
, testDistribution :: ()
testDistribution = ()
}
where
(Int
n,Double
tPlus,Double
tMinus) = forall a.
(Ord a, Num a, Unbox a) =>
Vector (a, a) -> (Int, Double, Double)
wilcoxonMatchedPairSignedRank Vector (a, a)
pairs
(Double
t,PValue Double
pVal) = case PositionTest
test of
PositionTest
AGreater -> (forall a. Num a => a -> a
abs Double
tMinus, Int -> Double -> PValue Double
wilcoxonMatchedPairSignificance Int
n (forall a. Num a => a -> a
abs Double
tMinus))
PositionTest
BGreater -> (forall a. Num a => a -> a
abs Double
tPlus, Int -> Double -> PValue Double
wilcoxonMatchedPairSignificance Int
n (forall a. Num a => a -> a
abs Double
tPlus ))
PositionTest
SamplesDiffer -> let t' :: Double
t' = forall a. Ord a => a -> a -> a
min (forall a. Num a => a -> a
abs Double
tMinus) (forall a. Num a => a -> a
abs Double
tPlus)
p :: PValue Double
p = Int -> Double -> PValue Double
wilcoxonMatchedPairSignificance Int
n Double
t'
in (Double
t', forall a. (Ord a, Num a) => a -> PValue a
mkPValue forall a b. (a -> b) -> a -> b
$ forall a. Ord a => a -> a -> a
min Double
1 forall a b. (a -> b) -> a -> b
$ Double
2 forall a. Num a => a -> a -> a
* forall a. PValue a -> a
pValue PValue Double
p)