heidi-0.0.0: src/Core/Data/Frame/List.hs
{-# language OverloadedStrings #-}
{-# language FlexibleInstances #-}
{-# language DeriveFunctor, DeriveFoldable, DeriveTraversable, GeneralizedNewtypeDeriving #-}
{-# language ConstraintKinds #-}
{-# OPTIONS_GHC -Wno-unused-top-binds #-}
{-# OPTIONS_GHC -Wno-type-defaults #-}
-----------------------------------------------------------------------------
-- |
-- Module : Core.Data.Frame.List
-- Description : List-based dataframe
-- Copyright : (c) Marco Zocca (2018-2019)
-- License : BSD-style
-- Maintainer : ocramz fripost org
-- Stability : experimental
-- Portability : GHC
--
-- A general-purpose, row-oriented data frame, encoded as a list of rows
--
-----------------------------------------------------------------------------
module Core.Data.Frame.List (
-- * Frame
Frame,
-- ** Construction
frameFromList,
-- ** Access
Core.Data.Frame.List.head,
Core.Data.Frame.List.take,
Core.Data.Frame.List.drop, Core.Data.Frame.List.zipWith, numRows,
-- ** Filtering
Core.Data.Frame.List.filter,
-- *** 'D.Decode'-based filtering helpers
filterA,
-- **
groupWith,
-- ** Scans (row-wise cumulative operations)
Core.Data.Frame.List.scanl, Core.Data.Frame.List.scanr,
-- ** Vector-related
toVector, fromVector,
-- *** Sorting
) where
import qualified Control.Monad as CM (filterM)
import Data.List (groupBy)
import qualified Data.Vector as V
-- | A 'Frame' is a list of rows.
newtype Frame row = Frame {
tableRows :: [row] } deriving (Show, Functor, Foldable, Traversable)
head :: Frame row -> row
head = Prelude.head . tableRows
-- | Retain n rows
take :: Int -> Frame row -> Frame row
take n = Frame . Prelude.take n . tableRows
-- | Drop n rows
drop :: Int -> Frame row -> Frame row
drop n = Frame . Prelude.drop n . tableRows
zipWith :: (a -> b -> c) -> Frame a -> Frame b -> Frame c
zipWith f x y = frameFromList $ Prelude.zipWith f (tableRows x) (tableRows y)
frameFromList :: [row] -> Frame row
frameFromList = Frame
toList :: Frame row -> [row]
toList = tableRows
numRows :: Frame row -> Int
numRows = length . tableRows
filter :: (row -> Bool) -> Frame row -> Frame row
filter p = Frame . Prelude.filter p . tableRows
-- | This generalizes the list-based 'filter' function.
filterA :: Applicative f =>
(row -> f Bool) -> Frame row -> f (Frame row)
filterA fm t = frameFromList <$> CM.filterM fm (toList t)
-- | Left-associative scan
scanl :: (b -> a -> b) -> b -> Frame a -> Frame b
scanl f z tt = Frame $ Prelude.scanl f z (tableRows tt)
-- | Right-associative scan
scanr :: (a -> b -> b) -> b -> Frame a -> Frame b
scanr f z tt = Frame $ Prelude.scanr f z (tableRows tt)
-- | 'groupWith' takes row comparison function and a list and returns a list of lists such that the concatenation of the result is equal to the argument. Moreover, each sublist in the result contains only elements that satisfy the comparison.
groupWith :: (row -> row -> Bool) -> Frame row -> [Frame row]
groupWith f t = Frame <$> groupBy f (tableRows t)
-- | Produce a 'Vector' of rows
toVector :: Frame row -> V.Vector row
toVector = V.fromList . tableRows
-- | Produce a Frame from a 'Vector' of rows
fromVector :: V.Vector row -> Frame row
fromVector = frameFromList . V.toList