{-# LANGUAGE BangPatterns #-}
module Statistics.RankProduct
( rankList
, rankProduct
, prerankProduct
, rankProductPermutation
, namedRankProductPermutation
) where
import Data.Function (on)
import Data.List
import Data.Random
import Statistics.Types
rankList :: (Ord a) => Sort -> [a] -> [Double]
rankList sortType = fmap fst
. sortBy (compare `on` (fst . snd))
. rankType sortType
. zip [1..]
. sortBy (compare `on` snd)
. zip [1..]
where
rankType Ascending = id
rankType Descending = (\(!xs, !ys) -> zip (reverse xs) ys) . unzip
rankProduct :: Sort -> [Entity] -> [RankProductEntity]
rankProduct sortType xs =
fmap ( RankProductEntity
. (** (1 / (genericLength . unEntity . head $ xs)))
. product
)
. transpose
. fmap (rankList sortType)
. transpose
. fmap unEntity
$ xs
prerankProduct :: [RankEntity] -> [RankProductEntity]
prerankProduct xs =
fmap
( RankProductEntity
. (** (1 / (genericLength . unRankEntity . head $ xs)))
. product
. unRankEntity
)
xs
permuteEntities :: [RankEntity] -> IO [RankEntity]
permuteEntities = fmap (fmap RankEntity . transpose)
. mapM (sample . shuffle)
. transpose
. fmap unRankEntity
boolToNum :: (Num a) => Bool -> a
boolToNum False = 0
boolToNum True = 1
rankProductPermutation :: Permutations
-> Sort
-> [Entity]
-> IO [(RankProductEntity, PValue)]
rankProductPermutation (Permutations permutations) sortType entities = do
let ranked = fmap RankEntity
. transpose
. fmap (rankList sortType)
. transpose
. fmap unEntity
$ entities
obs = prerankProduct ranked
expTest (RankProductEntity o) = (<= o) . unRankProductEntity
let successes :: [Int] -> Int -> IO [Int]
successes !acc 0 = return acc
successes !acc !n = do
shuffledEntities <- permuteEntities ranked
let res = prerankProduct shuffledEntities
success = zipWith (\o -> boolToNum . expTest o) obs res
successes (zipWith (+) acc success) (n - 1)
exp <- successes (take (genericLength entities) [0,0..]) permutations
let pVals =
fmap (\e -> PValue $ (fromIntegral e) / (fromIntegral permutations)) exp
return . zip obs $ pVals
namedRankProductPermutation :: Permutations
-> Sort
-> [NamedEntity]
-> IO [(Name, RankProductEntity, PValue)]
namedRankProductPermutation permutations sortType entities =
fmap (zipWith (\ !n (!r, !p) -> (n, r, p)) names)
. rankProductPermutation permutations sortType
. fmap (\(NamedEntity _ xs) -> Entity xs)
. filter ((== maxReplicates) . length . values)
$ entities
where
names = fmap name entities
maxReplicates = maximum . fmap (length . values) $ entities