datasets 0.2.2 → 0.2.3
raw patch · 8 files changed
+99/−56 lines, 8 filesPVP: major bump suggested
API removals or changes: PVP suggests a major version bump
API changes (from Hackage documentation)
- Numeric.Datasets: parseCSV :: FromRecord a => (ByteString -> ByteString) -> ByteString -> [a]
- Numeric.Datasets: parseCSVHdr :: FromNamedRecord a => ByteString -> [a]
- Numeric.Datasets: parseCSVHdrSep :: FromNamedRecord a => Char -> ByteString -> [a]
- Numeric.Datasets: parseJSON :: FromJSON a => ByteString -> [a]
- Numeric.Datasets: type Dataset a = FilePath Directory for caching downloaded datasets -> IO [a]
+ Numeric.Datasets: Dataset :: Source -> Maybe FilePath -> Maybe (ByteString -> ByteString) -> ReadAs a -> Dataset a
+ Numeric.Datasets: [CSVNamedRecord] :: FromNamedRecord a => DecodeOptions -> ReadAs a
+ Numeric.Datasets: [CSVRecord] :: FromRecord a => HasHeader -> DecodeOptions -> ReadAs a
+ Numeric.Datasets: [JSON] :: FromJSON a => ReadAs a
+ Numeric.Datasets: [preProcess] :: Dataset a -> Maybe (ByteString -> ByteString)
+ Numeric.Datasets: [readAs] :: Dataset a -> ReadAs a
+ Numeric.Datasets: [source] :: Dataset a -> Source
+ Numeric.Datasets: [temporaryDirectory] :: Dataset a -> Maybe FilePath
+ Numeric.Datasets: csvRecord :: FromRecord a => ReadAs a
+ Numeric.Datasets: data Dataset a
+ Numeric.Datasets: data ReadAs a
+ Numeric.Datasets: readDataset :: ReadAs a -> ByteString -> [a]
+ Numeric.Datasets.Coal: coal :: Dataset Coal
+ Numeric.Datasets.Coal: data Coal
+ Numeric.Datasets.Coal: date :: Coal -> Double
+ Numeric.Datasets.Coal: instance Data.Csv.Conversion.FromRecord Numeric.Datasets.Coal.Coal
+ Numeric.Datasets.Coal: instance GHC.Generics.Generic Numeric.Datasets.Coal.Coal
+ Numeric.Datasets.Coal: instance GHC.Read.Read Numeric.Datasets.Coal.Coal
+ Numeric.Datasets.Coal: instance GHC.Show.Show Numeric.Datasets.Coal.Coal
+ Numeric.Datasets.Iris: instance GHC.Classes.Ord Numeric.Datasets.Iris.IrisClass
+ Numeric.Datasets.OldFaithful: instance GHC.Show.Show Numeric.Datasets.OldFaithful.OldFaithful
Files
- changelog.md +8/−0
- datasets.cabal +2/−1
- src/Numeric/Datasets.hs +52/−50
- src/Numeric/Datasets/Coal.hs +31/−0
- src/Numeric/Datasets/Iris.hs +2/−2
- src/Numeric/Datasets/Michelson.hs +1/−1
- src/Numeric/Datasets/Nightingale.hs +1/−1
- src/Numeric/Datasets/OldFaithful.hs +2/−1
changelog.md view
@@ -1,3 +1,11 @@+0.2.3++* Coal dataset++* New internal API++* Ord instance for IrisClass+ 0.2.2 * Enum, bounded instances for IrisClass
datasets.cabal view
@@ -1,5 +1,5 @@ Name: datasets-Version: 0.2.2+Version: 0.2.3 Synopsis: Classical data sets for statistics and machine learning Description: Classical machine learning and statistics datasets from the UCI Machine Learning Repository and other sources.@@ -59,6 +59,7 @@ , Numeric.Datasets.Adult , Numeric.Datasets.BreastCancerWisconsin , Numeric.Datasets.Car+ , Numeric.Datasets.Coal , Numeric.Datasets.CO2 , Numeric.Datasets.Gapminder , Numeric.Datasets.Iris
src/Numeric/Datasets.hs view
@@ -16,7 +16,7 @@ -} -{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE OverloadedStrings, GADTs #-} module Numeric.Datasets where @@ -27,7 +27,7 @@ import Data.Monoid import qualified Data.ByteString.Lazy as BL import qualified Data.Vector as V-import qualified Data.Aeson as JSON+import Data.Aeson as JSON import Control.Applicative import Data.Time import Data.Char (ord)@@ -36,6 +36,7 @@ import Data.Char (toUpper) import Text.Read (readMaybe)+import Data.Maybe (fromMaybe) import Data.ByteString.Char8 (unpack) import qualified Data.ByteString.Lazy.Char8 as BL8 import Data.ByteString.Lazy.Search (replace)@@ -45,41 +46,72 @@ -- |Load a dataset, using the system temporary directory as a cache getDataset :: Dataset a -> IO [a] getDataset ds = do- dir <- getTemporaryDirectory- ds $ dir </> "haskds"---- | A dataset is defined as a function from the caching directory to the IO action that loads the data-type Dataset a = FilePath -- ^ Directory for caching downloaded datasets- -> IO [a]+ dir <- case temporaryDirectory ds of+ Nothing -> getTemporaryDirectory+ Just tdir -> return tdir+ bs <- fmap (fromMaybe id $ preProcess ds) $ getFileFromSource dir $ source ds+ return $ readDataset (readAs ds) bs --- * Defining datasets+-- |Read a ByteString into a Haskell value+readDataset :: ReadAs a -> BL.ByteString -> [a]+readDataset JSON bs =+ case JSON.decode bs of+ Just theData -> theData+ Nothing -> error "failed to parse json"+readDataset (CSVRecord hhdr opts) bs =+ case decodeWith opts hhdr bs of+ Right theData -> V.toList theData+ Left err -> error err+readDataset (CSVNamedRecord opts) bs =+ case decodeByNameWith opts bs of+ Right (_,theData) -> V.toList theData+ Left err -> error err data Source = URL String +-- | A dataset is a record telling us how to load the data++data Dataset a = Dataset+ { source :: Source+ , temporaryDirectory :: Maybe FilePath+ , preProcess :: Maybe (BL.ByteString -> BL.ByteString)+ , readAs :: ReadAs a+ }++-- | ReadAs is a datatype to describe data formats that hold data sets++data ReadAs a where+ JSON :: FromJSON a => ReadAs a+ CSVRecord :: FromRecord a => HasHeader -> DecodeOptions -> ReadAs a+ CSVNamedRecord :: FromNamedRecord a => DecodeOptions -> ReadAs a++csvRecord :: FromRecord a => ReadAs a+csvRecord = CSVRecord NoHeader defaultDecodeOptions++-- * Defining datasets+ -- |Define a dataset from a pre-processing function and a source for a CSV file csvDatasetPreprocess :: FromRecord a => (BL.ByteString -> BL.ByteString) -> Source -> Dataset a-csvDatasetPreprocess preF src cacheDir = do- parseCSV preF <$> getFileFromSource cacheDir src+csvDatasetPreprocess preF src = (csvDataset src) { preProcess = Just preF }+-- parseCSV preF <$> getFileFromSource cacheDir src -- |Define a dataset from a source for a CSV file csvDataset :: FromRecord a => Source -> Dataset a-csvDataset = csvDatasetPreprocess id+csvDataset src = Dataset src Nothing Nothing $ CSVRecord NoHeader defaultDecodeOptions -- |Define a dataset from a source for a CSV file with a known header csvHdrDataset :: FromNamedRecord a => Source -> Dataset a-csvHdrDataset src cacheDir = do- parseCSVHdr <$> getFileFromSource cacheDir src+csvHdrDataset src = Dataset src Nothing Nothing $ CSVNamedRecord defaultDecodeOptions -- |Define a dataset from a source for a CSV file with a known header and separator csvHdrDatasetSep :: FromNamedRecord a => Char -> Source -> Dataset a-csvHdrDatasetSep sepc src cacheDir = do- parseCSVHdrSep sepc <$> getFileFromSource cacheDir src+csvHdrDatasetSep sepc src+ = Dataset src Nothing Nothing+ $ CSVNamedRecord defaultDecodeOptions { decDelimiter = fromIntegral (ord sepc)} -- |Define a dataset from a source for a JSON file -- data file must be accessible with HTTP, not HTTPS-jsonDataset :: JSON.FromJSON a => Source -> Dataset a-jsonDataset src cacheDir = do- bs <- getFileFromSource cacheDir src- return $ parseJSON bs+jsonDataset :: FromJSON a => Source -> Dataset a+jsonDataset src = Dataset src Nothing Nothing JSON -- | Get a ByteString from the specified Source getFileFromSource :: FilePath -> Source -> IO (BL.ByteString)@@ -95,36 +127,6 @@ let bs = rsp ^. Wreq.responseBody BL.writeFile fnm bs return bs---- | Parse CSV file-parseCSV :: FromRecord a => (BL.ByteString -> BL.ByteString) -> BL.ByteString -> [a]-parseCSV preF contents =- case decode NoHeader (preF contents) of- Right theData -> V.toList theData- Left err -> error err---- | Parse CSV file with known header-parseCSVHdr :: FromNamedRecord a => BL.ByteString -> [a]-parseCSVHdr contents =- case decodeByName contents of- Right (_,theData) -> V.toList theData- Left err -> error err---- | Parse CSV file with known header-parseCSVHdrSep :: FromNamedRecord a => Char -> BL.ByteString -> [a]-parseCSVHdrSep sepc contents =- let opts = defaultDecodeOptions { decDelimiter = fromIntegral (ord sepc)} in- case decodeByNameWith opts contents of- Right (_,theData) -> V.toList theData- Left err -> error err---- | Parse JSON file-parseJSON :: JSON.FromJSON a => BL.ByteString -> [a]-parseJSON bs = case JSON.decode bs of- Just theData -> theData- Nothing -> error "failed to parse json"-- -- * Helper functions for parsing
+ src/Numeric/Datasets/Coal.hs view
@@ -0,0 +1,31 @@+{-# LANGUAGE DeriveGeneric, OverloadedStrings #-}+{-# LANGUAGE GADTs, QuasiQuotes, ViewPatterns, FlexibleContexts #-}++{-|++Coal data set++Dates of mining disasters, from the `coal` dataset in the R package `boot`.++For further information, see <http://vincentarelbundock.github.io/Rdatasets/doc/boot/coal.html>++-}++module Numeric.Datasets.Coal ( Coal, coal, date ) where++import Numeric.Datasets++import Data.Csv+import GHC.Generics+import Control.Applicative++data Coal = Coal+ { date :: Double+ } deriving (Show, Read, Generic)++instance FromRecord Coal where+ parseRecord v = Coal <$> v .! 1++coal :: Dataset Coal+coal = let src = URL "http://vincentarelbundock.github.io/Rdatasets/csv/boot/coal.csv"+ in Dataset src Nothing Nothing $ CSVRecord HasHeader defaultDecodeOptions
src/Numeric/Datasets/Iris.hs view
@@ -19,7 +19,7 @@ data IrisClass = Setosa | Versicolor | Virginica- deriving (Show, Read, Eq, Generic, Enum, Bounded)+ deriving (Show, Read, Eq, Ord, Generic, Enum, Bounded) instance FromField IrisClass where parseField "Iris-setosa" = return Setosa@@ -38,4 +38,4 @@ instance FromRecord Iris iris :: [Iris]-iris = parseCSV id $ fromStrict $(embedFile "datafiles/iris.data")+iris = readDataset csvRecord (fromStrict $(embedFile "datafiles/iris.data"))
src/Numeric/Datasets/Michelson.hs view
@@ -18,4 +18,4 @@ michelson :: [[Double]]-michelson = parseJSON $ fromStrict $(embedFile "datafiles/michelson.json")+michelson = readDataset JSON (fromStrict $(embedFile "datafiles/michelson.json"))
src/Numeric/Datasets/Nightingale.hs view
@@ -31,4 +31,4 @@ instance FromJSON Nightingale nightingale :: [Nightingale]-nightingale = parseJSON $ fromStrict $(embedFile "datafiles/nightingale.json")+nightingale = readDataset JSON $ fromStrict $(embedFile "datafiles/nightingale.json")
src/Numeric/Datasets/OldFaithful.hs view
@@ -18,7 +18,8 @@ { recordingDay :: Int -- ^ Recording day. 1-8: 1978, 16-23: 1979 , waiting :: Double -- ^ waiting time until next eruption , duration :: Double -- ^ duration of eruption in minutes- }+ } deriving Show+ -- The first comp oldFaithful :: [OldFaithful] oldFaithful =