packages feed

timeseries (empty) → 0.1.0

raw patch · 14 files changed

+596/−0 lines, 14 filesdep +Cabaldep +QuickCheckdep +basesetup-changed

Dependencies added: Cabal, QuickCheck, base, bytestring, bytestring-time, cassava, hspec, text, time, vector

Files

+ CHANGES.md view
@@ -0,0 +1,9 @@+# Version 0.1 (2016-12-13)++  * Implemented functions+    * slice+    * max+    * min+  * Implemented CSV reader+  * Implemented size function+  * Implemented valueAt function
+ LICENSE view
@@ -0,0 +1,27 @@+Copyright (c) 2014 Krzysztof Langner+All rights reserved.++Redistribution and use in source and binary forms, with or without+modification, are permitted provided that the following conditions+are met:++    * Redistributions of source code must retain the above copyright+      notice, this list of conditions and the following disclaimer.++    * Redistributions in binary form must reproduce the above+      copyright notice, this list of conditions and the following+      disclaimer in the documentation and/or other materials provided+      with the distribution.++THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.+
+ README.md view
@@ -0,0 +1,36 @@+[![Build Status](https://travis-ci.org/klangner/time-series-lib.svg?branch=master)](https://travis-ci.org/klangner/time-series-lib)+[![Hackage](https://img.shields.io/hackage/v/timeseries.svg)](https://hackage.haskell.org/package/timeseries)++# Welcome to Haskell Time Series library++Implemented functionality:+  * Base operations on time series (get value, slice, max etc.)+  * Reading from CSV file++++## Installation++```sh+stack setup+stack build+stack test+```+++# Join in!++We are happy to receive bug reports, fixes, documentation enhancements,+and other improvements.++Please report bugs via the+[github issue tracker](http://github.com/klangner/time-series-lib/issues).++Master [git repository](http://github.com/klangner/time-series-lib):++* `git clone https://github.com/klangner/time-series-lib.git`+++# Redistributing++time-series-lib source code is distributed under the BSD3 License.
+ Setup.hs view
@@ -0,0 +1,2 @@+import Distribution.Simple+main = defaultMain
+ benchmark/Benchmarks.hs view
@@ -0,0 +1,28 @@++import Criterion.Main+import Data.Time (UTCTime)+import Data.Time.Clock.POSIX (posixSecondsToUTCTime)+import qualified Data.TimeSeries as TS+++seriesSize :: Integer+seriesSize = 10^6++index :: Integer -> UTCTime+index n = posixSecondsToUTCTime (fromIntegral n)++lastIndex :: UTCTime+lastIndex = index (seriesSize - 1)++bigSeries :: TS.Series+bigSeries = TS.tsSeries [1..seriesSize] [1..]+++main :: IO ()+main = defaultMain+    [ bgroup "Big series"+        [ bench "size"  $ nf TS.size bigSeries+        , bench "valueAt"  $ nf (\xs -> TS.valueAt xs lastIndex) bigSeries+        , bench "slice"  $ nf (\xs -> TS.valueAt (TS.slice xs (index 2) lastIndex) (index 1)) bigSeries+        ]+    ]
+ src/Data/TimeSeries.hs view
@@ -0,0 +1,9 @@+-- | TimeSeries library+module Data.TimeSeries+    ( module Data.TimeSeries.Series+    , module Data.TimeSeries.CSVReader+    ) where+++import Data.TimeSeries.Series+import Data.TimeSeries.CSVReader
+ src/Data/TimeSeries/CSVReader.hs view
@@ -0,0 +1,37 @@+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE OverloadedStrings #-}++module Data.TimeSeries.CSVReader+    ( load+    )where+++import qualified Data.ByteString.Lazy as BS+import qualified Data.Text as T+import           Data.Csv+import qualified Data.Vector as V+import           Data.Time (UTCTime)++import           Data.TimeSeries.Series ( Series+                                        , emptySeries+                                        , series+                                        )+++-- | Load data from CSV file and create Time Series from it+-- As a first argument provide function to convert date from ByteString to UTCTime+load :: (T.Text -> UTCTime) -> FilePath -> IO Series+load ft filePath = do+    csvData <- BS.readFile filePath+    case decode HasHeader csvData of+        Left err -> do+            _ <- putStrLn err+            return emptySeries++        Right vs -> do+            let vs' = V.map (parseLine ft) vs+            return $ series (V.toList vs')+++parseLine :: (T.Text -> UTCTime) -> (T.Text, Double) -> (UTCTime, Double)+parseLine ft (date, value) = (ft date, value)
+ src/Data/TimeSeries/Series.hs view
@@ -0,0 +1,107 @@+{-# OPTIONS_GHC -funbox-strict-fields  #-}+{-|+Module:      Data.TimeSeries.Series+Copyright:   (c) 2016 Krzysztof Langner+License:     BSD3+Stability:   experimental+Portability: portable+Definition and basic operation on Series.+-}++module Data.TimeSeries.Series+    ( DataPoint+    , Series+    , Value+    , emptySeries+    , max+    , min+    , series+    , size+    , slice+    , tsSeries+    , valueAt+    ) where++import Prelude hiding (max, min)+import Data.Time (UTCTime)+import Data.Time.Clock.POSIX (posixSecondsToUTCTime)+++type Value = Double+data DataPoint = DP !UTCTime !Value+                 deriving (Show, Eq)++data Series = Series [DataPoint]+    deriving (Show, Eq)+++-- | Create empty series+emptySeries :: Series+emptySeries = Series []+++-- | Create empty series+series :: [(UTCTime, Double)] -> Series+series xs = Series $ map (\(x, y) -> DP x y) xs+++-- | Create time series from timestamps and values+--+-- >seriesFromSeconds [1, 2, 3] [41.3, 52.22, 3.0] == Series [DP 1970-01-01 00:00:01 UTC 2.3,DP 1970-01-01 00:00:02 UTC 4.5]+--+tsSeries :: [Integer] -> [Value] -> Series+tsSeries ts vs = Series (zipWith DP idx vs)+    where idx = map (posixSecondsToUTCTime . fromIntegral) ts+++-- | Get series size.+-- Complexity O(n)+--+-- >size (Series [DP 1 41.3, DP 2 52.22, DP 3 3.0]) == 3+--+size :: Series -> Int+size (Series xs) = length xs+++-- | Return data point value at given index+-- Complexity O(n)+--+-- >valueAt (Series [DP 1 41.3, DP 2 52.22, DP 3 3.0]) 2 == Just 52.22+-- >valueAt (Series [DP 1 41.3, DP 2 52.22, DP 3 3.0]) 5 == Nothing+--+valueAt :: Series -> UTCTime -> Maybe Value+valueAt (Series xs) ts = safeHead [y | DP x y <- xs, x == ts]+    where safeHead [] = Nothing+          safeHead (a:_) = Just a+++-- | Return series subset+-- Complexity O(n)+--+-- >slice (Series [DP 1 41.3, DP 2 52.22, DP 3 3.0]) 2 3 == Series [DP 2 52.22, DP 3 3.0]+-- >slice (Series [DP 1 41.3, DP 2 52.22, DP 3 3.0]) 5 23 == Series []+--+slice :: Series -> UTCTime -> UTCTime -> Series+slice (Series xs) start end = Series [DP x y | DP x y <- xs, x >= start && x <= end]+++-- | Return maximum value in the series+-- Complexity O(n)+--+-- >max (Series [DP 1 41.3, DP 2 52.22, DP 3 3.0]) == 52.22+-- >max (Series []) == 0+--+max :: Series -> Value+max (Series xs) = foldl (\d (DP _ y) -> max' d y) 0.0 xs+    where max' a b = if a > b then a else b++-- | Return maximum value in the series+-- Complexity O(n)+--+-- >min (Series [DP 1 41.3, DP 2 52.22, DP 3 3.0]) == 3.0+-- >min (Series []) == 0+--+min :: Series -> Value+min (Series xs) = foldl (\d (DP _ y) -> min' d y) maxValue xs+    where min' a b = if a < b then a else b+          maxValue = fromIntegral (maxBound :: Int)
+ test-src/Data/TimeSeries/CSVSpec.hs view
@@ -0,0 +1,17 @@+module Data.TimeSeries.CSVSpec (spec) where++import Test.Hspec+import Data.ByteString.Time (parseISODateTime)++import qualified Data.TimeSeries as TS+import qualified Data.TimeSeries.CSVReader as CSV+++spec :: Spec+spec = do++  describe "Reader" $ do++    it "co2 test data" $ do+        xs <- CSV.load parseISODateTime "testdata/co2.csv"+        TS.size xs `shouldBe` 192
+ test-src/Data/TimeSeries/SeriesSpec.hs view
@@ -0,0 +1,49 @@+module Data.TimeSeries.SeriesSpec (spec) where++import Test.Hspec+import Data.Time.Clock.POSIX (posixSecondsToUTCTime)++import qualified Data.TimeSeries as TS+++spec :: Spec+spec = do++  describe "Basic operations" $ do++    it "return series size" $ do+        let idx = [1, 2, 3]+        let values = [1.0, 2.0, 3.0]+        TS.size (TS.tsSeries idx values) `shouldBe` 3++    it "return data point value at given index" $ do+        let idx = [10, 20, 30]+        let values = [10.0, 12.0, 32.4]+        let pos = posixSecondsToUTCTime $ fromIntegral 20+        TS.valueAt (TS.tsSeries idx values) pos `shouldBe` Just 12.0++    it "return Nothing value if wrong index" $ do+        let idx = [10, 20, 30]+        let values = [10.0, 12.0, 32.4]+        let pos = posixSecondsToUTCTime $ fromIntegral 1234+        TS.valueAt (TS.tsSeries idx values) pos `shouldBe` Nothing++    it "return subset" $ do+        let xs = TS.tsSeries [1..5] [10.0, 1.2, 32.4, 0.65, 11.0]+        let start = posixSecondsToUTCTime $ fromIntegral 2+        let end = posixSecondsToUTCTime $ fromIntegral 3+        TS.size (TS.slice xs start end) `shouldBe` 2++    it "return empty subset" $ do+        let xs = TS.tsSeries [1..5] [10.0, 1.2, 32.4, 0.65, 11.0]+        let start = posixSecondsToUTCTime $ fromIntegral 12+        let end = posixSecondsToUTCTime $ fromIntegral 34+        TS.slice xs start end `shouldBe` TS.emptySeries++    it "maximum value" $ do+        let xs = TS.tsSeries [1..5] [10.0, 1.2, 32.4, 0.65, 11.0]+        TS.max xs `shouldBe` 32.4++    it "minimum value" $ do+        let xs = TS.tsSeries [1..5] [10.0, 1.2, 32.4, 0.65, 11.0]+        TS.min xs `shouldBe` 0.65
+ test-src/Spec.hs view
@@ -0,0 +1,9 @@+import Test.Hspec+import qualified Data.TimeSeries.SeriesSpec+import qualified Data.TimeSeries.CSVSpec+++main :: IO ()+main = hspec $ do+  describe "Series" Data.TimeSeries.SeriesSpec.spec+  describe "CSV" Data.TimeSeries.CSVSpec.spec
+ testdata/co2.csv view
@@ -0,0 +1,193 @@+"Month","CO2 (ppm) mauna loa, 1965-1980"
+"1965-01",319.32
+"1965-02",320.36
+"1965-03",320.82
+"1965-04",322.06
+"1965-05",322.17
+"1965-06",321.95
+"1965-07",321.20
+"1965-08",318.81
+"1965-09",317.82
+"1965-10",317.37
+"1965-11",318.93
+"1965-12",319.09
+"1966-01",319.94
+"1966-02",320.98
+"1966-03",321.81
+"1966-04",323.03
+"1966-05",323.36
+"1966-06",323.11
+"1966-07",321.65
+"1966-08",319.64
+"1966-09",317.86
+"1966-10",317.25
+"1966-11",319.06
+"1966-12",320.26
+"1967-01",321.65
+"1967-02",321.81
+"1967-03",322.36
+"1967-04",323.67
+"1967-05",324.17
+"1967-06",323.39
+"1967-07",321.93
+"1967-08",320.29
+"1967-09",318.58
+"1967-10",318.60
+"1967-11",319.98
+"1967-12",321.25
+"1968-01",321.88
+"1968-02",322.47
+"1968-03",323.17
+"1968-04",324.23
+"1968-05",324.88
+"1968-06",324.75
+"1968-07",323.47
+"1968-08",321.34
+"1968-09",319.56
+"1968-10",319.45
+"1968-11",320.45
+"1968-12",321.92
+"1969-01",323.40
+"1969-02",324.21
+"1969-03",325.33
+"1969-04",326.31
+"1969-05",327.01
+"1969-06",326.24
+"1969-07",325.37
+"1969-08",323.12
+"1969-09",321.85
+"1969-10",321.31
+"1969-11",322.31
+"1969-12",323.72
+"1970-01",324.60
+"1970-02",325.57
+"1970-03",326.55
+"1970-04",327.80
+"1970-05",327.80
+"1970-06",327.54
+"1970-07",326.28
+"1970-08",324.63
+"1970-09",323.12
+"1970-10",323.11
+"1970-11",323.99
+"1970-12",325.09
+"1971-01",326.12
+"1971-02",326.61
+"1971-03",327.16
+"1971-04",327.92
+"1971-05",329.14
+"1971-06",328.80
+"1971-07",327.52
+"1971-08",325.62
+"1971-09",323.61
+"1971-10",323.80
+"1971-11",325.10
+"1971-12",326.25
+"1972-01",326.93
+"1972-02",327.83
+"1972-03",327.95
+"1972-04",329.91
+"1972-05",330.22
+"1972-06",329.25
+"1972-07",328.11
+"1972-08",326.39
+"1972-09",324.97
+"1972-10",325.32
+"1972-11",326.54
+"1972-12",327.71
+"1973-01",328.73
+"1973-02",329.69
+"1973-03",330.47
+"1973-04",331.69
+"1973-05",332.65
+"1973-06",332.24
+"1973-07",331.03
+"1973-08",329.36
+"1973-09",327.60
+"1973-10",327.29
+"1973-11",328.28
+"1973-12",328.79
+"1974-01",329.45
+"1974-02",330.89
+"1974-03",331.63
+"1974-04",332.85
+"1974-05",333.28
+"1974-06",332.47
+"1974-07",331.34
+"1974-08",329.53
+"1974-09",327.57
+"1974-10",327.57
+"1974-11",328.53
+"1974-12",329.69
+"1975-01",330.45
+"1975-02",330.97
+"1975-03",331.64
+"1975-04",332.87
+"1975-05",333.61
+"1975-06",333.55
+"1975-07",331.90
+"1975-08",330.05
+"1975-09",328.58
+"1975-10",328.31
+"1975-11",329.41
+"1975-12",330.63
+"1976-01",331.63
+"1976-02",332.46
+"1976-03",333.36
+"1976-04",334.45
+"1976-05",334.82
+"1976-06",334.32
+"1976-07",333.05
+"1976-08",330.87
+"1976-09",329.24
+"1976-10",328.87
+"1976-11",330.18
+"1976-12",331.50
+"1977-01",332.81
+"1977-02",333.23
+"1977-03",334.55
+"1977-04",335.82
+"1977-05",336.44
+"1977-06",335.99
+"1977-07",334.65
+"1977-08",332.41
+"1977-09",331.32
+"1977-10",330.73
+"1977-11",332.05
+"1977-12",333.53
+"1978-01",334.66
+"1978-02",335.07
+"1978-03",336.33
+"1978-04",337.39
+"1978-05",337.65
+"1978-06",337.57
+"1978-07",336.25
+"1978-08",334.39
+"1978-09",332.44
+"1978-10",332.25
+"1978-11",333.59
+"1978-12",334.76
+"1979-01",335.89
+"1979-02",336.44
+"1979-03",337.63
+"1979-04",338.54
+"1979-05",339.06
+"1979-06",338.95
+"1979-07",337.41
+"1979-08",335.71
+"1979-09",333.68
+"1979-10",333.69
+"1979-11",335.05
+"1979-12",336.53
+"1980-01",337.81
+"1980-02",338.16
+"1980-03",339.88
+"1980-04",340.57
+"1980-05",341.19
+"1980-06",340.87
+"1980-07",339.25
+"1980-08",337.19
+"1980-09",335.49
+"1980-10",336.63
+"1980-11",337.74
+"1980-12",338.36
+ testdata/small.csv view
@@ -0,0 +1,5 @@+"Month","CO2 (ppm) mauna loa, 1965-1980"
+"1965-01",319.32
+"1965-02",320.36
+"1965-03",320.82
+"1965-04",322.06
+ timeseries.cabal view
@@ -0,0 +1,68 @@+name:           timeseries+version:        0.1.0+synopsis:       Library for Time Series processing+License:        BSD3+License-file:   LICENSE+Copyright:      (c) 2016 Krzysztof Langner+Extra-Source-Files:+                README.md,+                CHANGES.md,+                LICENSE,+                benchmark/*.hs,+                testdata/*.csv+description:+    Library for processing time series data.++homepage:       https://github.com/klangner/timeseries+author:         Krzysztof Langner+maintainer:     klangner@gmail.com+category:       Data+build-type:     Simple+cabal-version:  >=1.10++source-repository head+  type:     git+  location: https://github.com/klangner/timeseries++library+  hs-source-dirs:   src+  default-language: Haskell2010+  ghc-options:      -Wall+  build-depends:+                    base >= 4.7 && < 5,+                    bytestring < 0.11,+                    bytestring-time < 1,+                    cassava >= 0.4 && < 0.5,+                    text < 2,+                    time >= 1.5 && < 2,+                    vector < 0.12+  exposed-modules:+                    Data.TimeSeries+  other-modules:+                    Data.TimeSeries.Series,+                    Data.TimeSeries.CSVReader++test-suite unit-tests+  type:             exitcode-stdio-1.0+  main-is:          Spec.hs+  default-language: Haskell2010+  build-depends:+                    base >= 4 && <5,+                    Cabal <2,+                    hspec >=2 && <3,+                    QuickCheck >=2.6 && <3,+                    bytestring < 0.11,+                    bytestring-time < 1,+                    cassava >= 0.4 && < 0.5,+                    text < 2,+                    time >= 1.5 && < 2,+                    vector < 0.12+  other-modules:+                    Data.TimeSeries,+                    Data.TimeSeries.Series,+                    Data.TimeSeries.SeriesSpec+                    Data.TimeSeries.CSVReader+                    Data.TimeSeries.CSVSpec+  hs-source-dirs:+                    src,+                    test-src