numhask-histogram 0.1.3.0 → 0.2.0
raw patch · 4 files changed
+55/−67 lines, 4 filesdep +numhask-spacedep −numhask-preludedep −numhask-range
Dependencies added: numhask-space
Dependencies removed: numhask-prelude, numhask-range
Files
- numhask-histogram.cabal +4/−12
- src/NumHask/Histogram.hs +48/−48
- stack.yaml +2/−5
- test/test.hs +1/−2
numhask-histogram.cabal view
@@ -1,11 +1,5 @@--- This file has been generated from package.yaml by hpack version 0.28.2.------ see: https://github.com/sol/hpack------ hash: 06f538b0715c38391805b7491f4212890c30f2d6111828cac2bb0d2db59602f5- name: numhask-histogram-version: 0.1.3.0+version: 0.2.0 synopsis: See readme.md description: See readme.md for description. category: project@@ -17,7 +11,7 @@ license: BSD3 license-file: LICENSE build-type: Simple-cabal-version: >= 1.10+cabal-version: 1.12 extra-source-files: stack.yaml @@ -28,14 +22,13 @@ library hs-source-dirs: src- default-extensions: NegativeLiterals NoImplicitPrelude OverloadedStrings UnicodeSyntax+ default-extensions: NegativeLiterals OverloadedStrings UnicodeSyntax ghc-options: -Wall -Wcompat -Wincomplete-record-updates -Wincomplete-uni-patterns -Wredundant-constraints -Wall build-depends: base >=4.7 && <5 , containers , foldl- , numhask-prelude >=0.1.0.1- , numhask-range >=0.2.3.0+ , numhask-space , tdigest exposed-modules: NumHask.Histogram@@ -53,7 +46,6 @@ build-depends: base >=4.7 && <5 , doctest- , numhask-prelude >=0.0.5.1 other-modules: Paths_numhask_histogram default-language: Haskell2010
src/NumHask/Histogram.hs view
@@ -1,34 +1,37 @@ {-# LANGUAGE DataKinds #-}-{-# LANGUAGE NoImplicitPrelude #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE TupleSections #-} {-# OPTIONS_GHC -Wall #-} module NumHask.Histogram- ( Histogram(..)- , DealOvers(..)- , fill- , regular- , makeRects- , regularQuantiles- , quantileFold- , fromQuantiles- , freq- ) where+ ( Histogram (..),+ DealOvers (..),+ fill,+ regular,+ makeRects,+ regularQuantiles,+ quantileFold,+ fromQuantiles,+ freq,+ )+where -import Data.TDigest-import NumHask.Prelude-import NumHask.Range-import NumHask.Rect-import NumHask.Space-import qualified Data.Map as Map import qualified Control.Foldl as L import qualified Data.List+import qualified Data.Map as Map+import Data.Maybe+import Data.TDigest+import NumHask.Space+import Prelude -- | a Histogram is a list of contiguous boundaries (a boundary being the lower edge of one bucket and the upper edge of another), and a count for each bucket -- Overs and Unders are counted in key=0 and key=length cut-data Histogram = Histogram- { cuts :: [Double] -- bucket boundaries- , values :: Map.Map Int Double -- bucket counts- } deriving (Show, Eq)+data Histogram+ = Histogram+ { cuts :: [Double], -- bucket boundaries+ values :: Map.Map Int Double -- bucket counts+ }+ deriving (Show, Eq) -- | whether or not to ignore unders and overs data DealOvers = IgnoreOvers | IncludeOvers Double@@ -39,52 +42,51 @@ fill :: (Functor f, Foldable f) => [Double] -> f Double -> Histogram fill cs xs = Histogram cs (histMap cs xs) where- histMap cs' xs' = L.fold count $+ histMap cs' xs' =+ L.fold count $ (\x -> L.fold countBool (fmap (x >) cs')) <$> xs'- count = L.premap (\x -> (x,1.0)) countW- countBool = L.Fold (\x a -> x + if a then 1 else 0) 0 identity- countW = L.Fold (\x (a,w) -> Map.insertWith (+) a w x) Map.empty identity+ count = L.premap (,1.0) countW+ countBool = L.Fold (\x a -> x + if a then 1 else 0) 0 id+ countW = L.Fold (\x (a, w) -> Map.insertWith (+) a w x) Map.empty id -- | make a histogram using n equally spaced cuts over the entire range of the data -- >>> regular 4 [0..100] -- Histogram {cuts = [0.0,25.0,50.0,75.0,100.0], values = fromList [(0,1.0),(1,25.0),(2,25.0),(3,25.0),(4,25.0)]}--- regular :: Int -> [Double] -> Histogram regular n xs = fill cs xs where- cs = grid OuterPos (space xs :: Range Double) n+ cs = grid OuterPos (space1 xs :: Range Double) n -- | transform a Histogram to Rects -- >>> makeRects IgnoreOvers (regular 4 [0..100]) -- [Rect 0.0 25.0 0.0 0.25,Rect 25.0 50.0 0.0 0.25,Rect 50.0 75.0 0.0 0.25,Rect 75.0 100.0 0.0 0.25]--- makeRects :: DealOvers -> Histogram -> [Rect Double] makeRects o (Histogram cs counts) = Data.List.zipWith4 Rect x z y w' where y = repeat 0- w = zipWith (/)- ((\x' -> Map.findWithDefault 0 x' counts) <$> [f..l])+ w =+ zipWith+ (/)+ ((\x' -> Map.findWithDefault 0 x' counts) <$> [f .. l]) (zipWith (-) z x) f = case o of- IgnoreOvers -> 1- IncludeOvers _ -> 0+ IgnoreOvers -> 1+ IncludeOvers _ -> 0 l = case o of- IgnoreOvers -> length cs - 1- IncludeOvers _ -> length cs- w' = (/sum w) <$> w+ IgnoreOvers -> length cs - 1+ IncludeOvers _ -> length cs+ w' = (/ sum w) <$> w x = case o of- IgnoreOvers -> cs- IncludeOvers outw ->- [Data.List.head cs - outw] <>- cs <>- [Data.List.last cs + outw]+ IgnoreOvers -> cs+ IncludeOvers outw ->+ [Data.List.head cs - outw]+ <> cs+ <> [Data.List.last cs + outw] z = drop 1 x - -- | approx regular n-quantiles -- >>> regularQuantiles 4 [0..100] -- [0.0,24.75,50.0,75.25,100.0]--- regularQuantiles :: Double -> [Double] -> [Double] regularQuantiles n = L.fold (quantileFold qs) where@@ -96,23 +98,21 @@ where step x a = Data.TDigest.insert a x begin = tdigest ([] :: [Double]) :: TDigest 25- done x = fromMaybe nan . (`quantile` compress x) <$> qs+ done x = fromMaybe (0 / 0) . (`quantile` compress x) <$> qs -- | take a specification of quantiles and make a Histogram -- >>> fromQuantiles [0,0.25,0.5,0.75,1] (regularQuantiles 4 [0..100]) -- Histogram {cuts = [0.0,24.75,50.0,75.25,100.0], values = fromList [(1,0.25),(2,0.25),(3,0.25),(4,0.25)]}--- fromQuantiles :: [Double] -> [Double] -> Histogram-fromQuantiles qs xs = Histogram xs (Map.fromList $ zip [1..] (diffq qs))+fromQuantiles qs xs = Histogram xs (Map.fromList $ zip [1 ..] (diffq qs)) where diffq [] = [] diffq [_] = []- diffq (x:xs') = L.fold (L.Fold step (x,[]) (reverse . snd)) xs'- step (a0,xs') a = (a,(a-a0):xs')+ diffq (x : xs') = L.fold (L.Fold step (x, []) (reverse . snd)) xs'+ step (a0, xs') a = (a, (a - a0) : xs') -- | normalize a histogram so that sum values = one -- >>> freq $ fill [0,50,100] [1..100] -- Histogram {cuts = [0.0,50.0,100.0], values = fromList [(1,0.5),(2,0.5)]}--- freq :: Histogram -> Histogram freq (Histogram cs vs) = Histogram cs $ Map.map (* recip (sum vs)) vs
stack.yaml view
@@ -1,13 +1,10 @@-resolver: nightly-2018-05-28+resolver: lts-14.13 packages: - .- - ../numhask-range extra-deps: - tdigest-0.2- - numhask-prelude-0.1.0.1- - numhask-0.2.3.0- - numhask-test-0.1.0.0+ - numhask-space-0.2.0 allow-newer: true
test/test.hs view
@@ -1,9 +1,8 @@-{-# LANGUAGE NoImplicitPrelude #-} {-# OPTIONS_GHC -Wall #-} module Main where -import NumHask.Prelude+import Prelude import Test.DocTest main :: IO ()