diff --git a/changelog.md b/changelog.md
--- a/changelog.md
+++ b/changelog.md
@@ -1,3 +1,11 @@
+0.2.1
+
+* Wine quality datasets
+
+* Vocabulary, UN, States datasets
+
+* CO2, Sunspots and Quakes datasets
+
 0.2.0.3
 
 * Further GHC portability
diff --git a/datasets.cabal b/datasets.cabal
--- a/datasets.cabal
+++ b/datasets.cabal
@@ -1,5 +1,5 @@
 Name:                datasets
-Version:             0.2.0.3
+Version:             0.2.1
 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,10 +59,17 @@
                  , Numeric.Datasets.Adult
                  , Numeric.Datasets.BreastCancerWisconsin
                  , Numeric.Datasets.Car
+                 , Numeric.Datasets.CO2
                  , Numeric.Datasets.Iris
                  , Numeric.Datasets.Michelson
                  , Numeric.Datasets.Nightingale
+                 , Numeric.Datasets.Quakes
+                 , Numeric.Datasets.States
+                 , Numeric.Datasets.Sunspots
+                 , Numeric.Datasets.UN
+                 , Numeric.Datasets.Vocabulary
                  , Numeric.Datasets.Wine
+                 , Numeric.Datasets.WineQuality
    Build-depends:
                  base                    >= 4.6 && < 5
                , cassava
diff --git a/src/Numeric/Datasets.hs b/src/Numeric/Datasets.hs
--- a/src/Numeric/Datasets.hs
+++ b/src/Numeric/Datasets.hs
@@ -30,6 +30,8 @@
 import qualified Data.Vector as V
 import qualified Data.Aeson as JSON
 import Control.Applicative
+import Data.Time
+import Data.Char (ord)
 
 import Data.Char (toUpper)
 import Text.Read (readMaybe)
@@ -62,6 +64,17 @@
 csvDataset :: FromRecord a =>  Source -> Dataset a
 csvDataset  = csvDatasetPreprocess id
 
+-- |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
+
+-- |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
+
+-- |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
@@ -84,12 +97,29 @@
        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
@@ -139,3 +169,15 @@
   chomp (' ':cs) = chomp cs
   chomp (c:cs) = c:cs
   chomp [] = []
+
+-- * Helper functions for data analysis
+
+-- | convert a fractional year to UTCTime with second-level precision (due to not taking into account leap seconds)
+yearToUTCTime :: Double -> UTCTime
+yearToUTCTime yearDbl =
+  let (yearn,yearFrac)  = properFraction yearDbl
+      dayYearBegin = fromGregorian yearn 1 1
+      (dayn, dayFrac) = properFraction $ yearFrac * (if isLeapYear yearn then 366 else 365)
+      day = addDays dayn dayYearBegin
+      dt = secondsToDiffTime $ round $ dayFrac * 86400
+  in UTCTime day dt
diff --git a/src/Numeric/Datasets/CO2.hs b/src/Numeric/Datasets/CO2.hs
new file mode 100644
--- /dev/null
+++ b/src/Numeric/Datasets/CO2.hs
@@ -0,0 +1,30 @@
+{-# LANGUAGE DeriveGeneric, OverloadedStrings #-}
+
+{-|
+
+Mauna Loa CO2 time-series
+
+
+Listed as co2 here: http://vincentarelbundock.github.io/Rdatasets/datasets.html
+
+See <http://vincentarelbundock.github.io/Rdatasets/doc/datasets/co2.html>
+
+-}
+
+module Numeric.Datasets.CO2 where
+
+import Numeric.Datasets
+
+import Data.Csv
+import GHC.Generics
+
+data CO2 = CO2
+  { time :: Double
+  , co2 :: Double
+  } deriving (Show, Read, Generic)
+
+instance FromNamedRecord CO2
+
+maunaLoaCO2 :: Dataset CO2
+maunaLoaCO2 = csvHdrDataset
+   $ URL "http://vincentarelbundock.github.io/Rdatasets/csv/datasets/co2.csv"
diff --git a/src/Numeric/Datasets/Quakes.hs b/src/Numeric/Datasets/Quakes.hs
new file mode 100644
--- /dev/null
+++ b/src/Numeric/Datasets/Quakes.hs
@@ -0,0 +1,31 @@
+{-# LANGUAGE DeriveGeneric, OverloadedStrings #-}
+
+{-|
+
+Locations of Earthquakes off Fiji
+
+Listed as quakes here: http://vincentarelbundock.github.io/Rdatasets/datasets.html
+
+
+-}
+
+module Numeric.Datasets.Quakes where
+
+import Numeric.Datasets
+
+import Data.Csv
+import GHC.Generics
+
+data Quake = Quake
+  { lat :: Double
+  , long :: Double
+  , depth :: Double
+  , mag :: Double
+  , stations :: Int
+  } deriving (Show, Read, Generic)
+
+instance FromNamedRecord Quake
+
+quakes :: Dataset Quake
+quakes = csvHdrDataset
+   $ URL "http://vincentarelbundock.github.io/Rdatasets/csv/datasets/quakes.csv"
diff --git a/src/Numeric/Datasets/States.hs b/src/Numeric/Datasets/States.hs
new file mode 100644
--- /dev/null
+++ b/src/Numeric/Datasets/States.hs
@@ -0,0 +1,43 @@
+{-# LANGUAGE DeriveGeneric, OverloadedStrings #-}
+
+{-|
+
+Data on education in US states
+
+<http://vincentarelbundock.github.io/Rdatasets/doc/car/States.html>
+
+-}
+
+module Numeric.Datasets.States where
+
+import Numeric.Datasets
+
+import Data.Csv
+import GHC.Generics
+import Control.Applicative
+
+data StateEdu = StateEdu
+  { state :: String
+  , region :: String
+  , population :: Int
+  , satVerbal :: Int
+  , satMath :: Int
+  , satPercent :: Int
+  , dollarSpend :: Double
+  , teacherPay :: Int
+  } deriving (Show, Read, Generic)
+
+instance FromNamedRecord StateEdu where
+    parseNamedRecord m = StateEdu <$>
+                         m .: "" <*>
+                         m .: "region"  <*>
+                         m .: "pop"  <*>
+                         m .: "SATV"  <*>
+                         m .: "SATM"  <*>
+                         m .: "percent"  <*>
+                         m .: "dollars"  <*>
+                         m .: "pay"
+
+states :: Dataset StateEdu
+states = csvHdrDataset
+   $ URL "http://vincentarelbundock.github.io/Rdatasets/csv/car/States.csv"
diff --git a/src/Numeric/Datasets/Sunspots.hs b/src/Numeric/Datasets/Sunspots.hs
new file mode 100644
--- /dev/null
+++ b/src/Numeric/Datasets/Sunspots.hs
@@ -0,0 +1,33 @@
+{-# LANGUAGE DeriveGeneric, OverloadedStrings #-}
+
+{-|
+
+Monthly sunspots from 1749
+
+Listed as sunspot.month here: http://vincentarelbundock.github.io/Rdatasets/datasets.html
+
+See <http://vincentarelbundock.github.io/Rdatasets/doc/datasets/sunspot.month.html>
+
+-}
+
+module Numeric.Datasets.Sunspots where
+
+import Numeric.Datasets
+
+import Data.Csv
+import GHC.Generics
+import Control.Applicative
+
+data Sunspot = Sunspot
+  { time :: Double
+  , sunspotMonth :: Double
+  } deriving (Show, Read, Generic)
+
+instance FromNamedRecord Sunspot where
+    parseNamedRecord m = Sunspot <$>
+                         m .: "time" <*>
+                         m .: "sunspot.month"
+
+sunspots :: Dataset Sunspot
+sunspots = csvHdrDataset
+   $ URL "http://vincentarelbundock.github.io/Rdatasets/csv/datasets/sunspot.month.csv"
diff --git a/src/Numeric/Datasets/UN.hs b/src/Numeric/Datasets/UN.hs
new file mode 100644
--- /dev/null
+++ b/src/Numeric/Datasets/UN.hs
@@ -0,0 +1,33 @@
+{-# LANGUAGE DeriveGeneric, OverloadedStrings #-}
+
+{-|
+
+GDP and infant mortality
+
+<http://vincentarelbundock.github.io/Rdatasets/doc/car/UN.html>
+
+-}
+
+module Numeric.Datasets.UN where
+
+import Numeric.Datasets
+
+import Data.Csv
+import GHC.Generics
+import Control.Applicative
+
+data GdpMortality = GdpMortality
+  { country :: String
+  , infantMortality :: Maybe Int
+  , gdp :: Maybe Int
+  } deriving (Show, Read, Generic)
+
+instance FromNamedRecord GdpMortality where
+    parseNamedRecord m = GdpMortality <$>
+                         m .: "" <*>
+                         (m .: "infant.mortality" <|> return Nothing) <*>
+                         (m .: "gdp" <|> return Nothing)
+
+gdpMortalityUN :: Dataset GdpMortality
+gdpMortalityUN = csvHdrDataset
+   $ URL "http://vincentarelbundock.github.io/Rdatasets/csv/car/UN.csv"
diff --git a/src/Numeric/Datasets/Vocabulary.hs b/src/Numeric/Datasets/Vocabulary.hs
new file mode 100644
--- /dev/null
+++ b/src/Numeric/Datasets/Vocabulary.hs
@@ -0,0 +1,35 @@
+{-# LANGUAGE DeriveGeneric, OverloadedStrings #-}
+
+{-|
+
+Vocabulary and Education
+
+<http://vincentarelbundock.github.io/Rdatasets/doc/car/Vocab.html>
+
+-}
+
+module Numeric.Datasets.Vocabulary where
+
+import Numeric.Datasets
+
+import Data.Csv
+import GHC.Generics
+
+data Sex = Female | Male
+  deriving (Show, Read, Eq, Generic)
+
+instance FromField Sex where
+  parseField = parseReadField
+
+data Vocab = Vocab
+  { year :: Integer
+  , sex :: Sex
+  , education :: Int
+  , vocabulary :: Int
+  } deriving (Show, Read, Generic)
+
+instance FromNamedRecord Vocab
+
+vocab :: Dataset Vocab
+vocab = csvHdrDataset
+   $ URL "http://vincentarelbundock.github.io/Rdatasets/csv/car/Vocab.csv"
diff --git a/src/Numeric/Datasets/WineQuality.hs b/src/Numeric/Datasets/WineQuality.hs
new file mode 100644
--- /dev/null
+++ b/src/Numeric/Datasets/WineQuality.hs
@@ -0,0 +1,54 @@
+{-# LANGUAGE DeriveGeneric, OverloadedStrings #-}
+
+{-|
+
+Quality of red and white wines based on physicochemical properties
+
+See <http://mlr.cs.umass.edu/ml/datasets/Wine+Quality>
+
+-}
+
+module Numeric.Datasets.WineQuality where
+
+import Numeric.Datasets
+
+import Data.Csv
+import GHC.Generics
+import Control.Applicative
+
+data WineQuality = WineQuality
+  { fixedAcidity :: Double
+  , volatileAcidity :: Double
+  , citricAcid :: Double
+  , residualSugar :: Double
+  , chlorides :: Double
+  , freeSulfurDioxide :: Double
+  , totalSulfurDioxide :: Double
+  , density :: Double
+  , pH :: Double
+  , sulphates :: Double
+  , alcohol :: Double
+  , quality :: Int
+  } deriving (Show, Read, Generic)
+
+instance FromNamedRecord WineQuality where
+    parseNamedRecord m = WineQuality <$>
+                         m .: "fixed acidity" <*>
+                         m .: "volatile acidity" <*>
+                         m .: "citric acid" <*>
+                         m .: "residual sugar" <*>
+                         m .: "chlorides" <*>
+                         m .: "free sulfur dioxide" <*>
+                         m .: "total sulfur dioxide" <*>
+                         m .: "density" <*>
+                         m .: "pH" <*>
+                         m .: "sulphates" <*>
+                         m .: "alcohol" <*>
+                         m .: "quality"
+
+redWineQuality, whiteWineQuality :: Dataset WineQuality
+redWineQuality = csvHdrDatasetSep ';'
+   $ URL "http://mlr.cs.umass.edu/ml/machine-learning-databases/wine-quality/winequality-red.csv"
+
+whiteWineQuality = csvHdrDatasetSep ';'
+   $ URL "http://mlr.cs.umass.edu/ml/machine-learning-databases/wine-quality/winequality-white.csv"
