dataframe-operations-2.0.0.0: src/DataFrame/Typed/Expr/Extra.hs
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE ScopedTypeVariables #-}
{- | Typed counterparts of the remaining "DataFrame.Functions" expression
combinators not already provided by "DataFrame.Typed.Expr". Each wraps the
untyped combinator 1:1, replacing @Expr@ with @'TExpr' cols@ so column
references stay schema-checked. Re-exported from "DataFrame.Typed.Expr".
-}
module DataFrame.Typed.Expr.Extra (
div,
mod,
mode,
sumMaybe,
meanMaybe,
variance,
medianMaybe,
percentile,
stddev,
stddevMaybe,
zScore,
pow,
relu,
min,
max,
reduce,
toMaybe,
fromMaybe,
isJust,
isNothing,
fromJust,
whenPresent,
whenBothPresent,
recode,
recodeWithCondition,
recodeWithDefault,
firstOrNothing,
lastOrNothing,
splitOn,
match,
matchAll,
parseDate,
daysBetween,
bind,
) where
import qualified Data.Text as T
import Data.Time (Day, ParseTime)
import qualified Data.Vector.Unboxed as VU
import Prelude hiding (div, max, min, mod)
import qualified DataFrame.Functions as F
import DataFrame.Internal.Column (Columnable)
import DataFrame.Typed.Types (TExpr (..))
-- | Integer division.
div ::
(Integral a, Columnable a) => TExpr cols a -> TExpr cols a -> TExpr cols a
div (TExpr a) (TExpr b) = TExpr (F.div a b)
-- | Integer modulus.
mod ::
(Integral a, Columnable a) => TExpr cols a -> TExpr cols a -> TExpr cols a
mod (TExpr a) (TExpr b) = TExpr (F.mod a b)
-- | Most frequent value (aggregation).
mode :: (Ord a, Columnable a, Eq a) => TExpr cols a -> TExpr cols a
mode (TExpr e) = TExpr (F.mode e)
-- | Sum of a nullable column, ignoring 'Nothing' (aggregation).
sumMaybe :: (Columnable a, Num a) => TExpr cols (Maybe a) -> TExpr cols a
sumMaybe (TExpr e) = TExpr (F.sumMaybe e)
-- | Mean of a nullable column, ignoring 'Nothing' (aggregation).
meanMaybe :: (Columnable a, Real a) => TExpr cols (Maybe a) -> TExpr cols Double
meanMaybe (TExpr e) = TExpr (F.meanMaybe e)
-- | Variance (aggregation).
variance ::
(Columnable a, Real a, VU.Unbox a) => TExpr cols a -> TExpr cols Double
variance (TExpr e) = TExpr (F.variance e)
-- | Median of a nullable column, ignoring 'Nothing' (aggregation).
medianMaybe ::
(Columnable a, Real a) => TExpr cols (Maybe a) -> TExpr cols Double
medianMaybe (TExpr e) = TExpr (F.medianMaybe e)
-- | The @n@-th percentile (aggregation).
percentile :: Int -> TExpr cols Double -> TExpr cols Double
percentile n (TExpr e) = TExpr (F.percentile n e)
-- | Standard deviation (aggregation).
stddev ::
(Columnable a, Real a, VU.Unbox a) => TExpr cols a -> TExpr cols Double
stddev (TExpr e) = TExpr (F.stddev e)
-- | Standard deviation of a nullable column, ignoring 'Nothing' (aggregation).
stddevMaybe ::
(Columnable a, Real a) => TExpr cols (Maybe a) -> TExpr cols Double
stddevMaybe (TExpr e) = TExpr (F.stddevMaybe e)
-- | Z-score (value minus group mean, over standard deviation).
zScore :: TExpr cols Double -> TExpr cols Double
zScore (TExpr e) = TExpr (F.zScore e)
-- | Raise an expression to an integer power.
pow :: (Columnable a, Num a) => TExpr cols a -> Int -> TExpr cols a
pow (TExpr e) i = TExpr (F.pow e i)
-- | Rectified linear unit: @max 0@.
relu :: (Columnable a, Num a, Ord a) => TExpr cols a -> TExpr cols a
relu (TExpr e) = TExpr (F.relu e)
-- | Element-wise minimum of two expressions.
min :: (Columnable a, Ord a) => TExpr cols a -> TExpr cols a -> TExpr cols a
min (TExpr a) (TExpr b) = TExpr (F.min a b)
-- | Element-wise maximum of two expressions.
max :: (Columnable a, Ord a) => TExpr cols a -> TExpr cols a -> TExpr cols a
max (TExpr a) (TExpr b) = TExpr (F.max a b)
-- | Fold a column into a single value with a seed and step function (aggregation).
reduce ::
(Columnable a, Columnable b) =>
TExpr cols b -> a -> (a -> b -> a) -> TExpr cols a
reduce (TExpr e) start f = TExpr (F.reduce e start f)
-- | Wrap each value in 'Just'.
toMaybe :: (Columnable a) => TExpr cols a -> TExpr cols (Maybe a)
toMaybe (TExpr e) = TExpr (F.toMaybe e)
-- | Replace 'Nothing' with a default.
fromMaybe :: (Columnable a) => a -> TExpr cols (Maybe a) -> TExpr cols a
fromMaybe d (TExpr e) = TExpr (F.fromMaybe d e)
-- | True where the value is 'Just'.
isJust :: (Columnable a) => TExpr cols (Maybe a) -> TExpr cols Bool
isJust (TExpr e) = TExpr (F.isJust e)
-- | True where the value is 'Nothing'.
isNothing :: (Columnable a) => TExpr cols (Maybe a) -> TExpr cols Bool
isNothing (TExpr e) = TExpr (F.isNothing e)
-- | Unwrap a 'Just', erroring on 'Nothing'.
fromJust :: (Columnable a) => TExpr cols (Maybe a) -> TExpr cols a
fromJust (TExpr e) = TExpr (F.fromJust e)
-- | Apply a function only where the value is present.
whenPresent ::
(Columnable a, Columnable b) =>
(a -> b) -> TExpr cols (Maybe a) -> TExpr cols (Maybe b)
whenPresent f (TExpr e) = TExpr (F.whenPresent f e)
-- | Apply a binary function only where both values are present.
whenBothPresent ::
(Columnable a, Columnable b, Columnable c) =>
(a -> b -> c) ->
TExpr cols (Maybe a) ->
TExpr cols (Maybe b) ->
TExpr cols (Maybe c)
whenBothPresent f (TExpr a) (TExpr b) = TExpr (F.whenBothPresent f a b)
-- | Map values through a lookup table, yielding 'Nothing' for misses.
recode ::
(Columnable a, Columnable b, Show a, Show b, Show (a, b)) =>
[(a, b)] -> TExpr cols a -> TExpr cols (Maybe b)
recode mapping (TExpr e) = TExpr (F.recode mapping e)
-- | Pick the first value whose condition holds, else a fallback.
recodeWithCondition ::
(Columnable a, Columnable b) =>
TExpr cols b ->
[(TExpr cols a -> TExpr cols Bool, b)] ->
TExpr cols a ->
TExpr cols b
recodeWithCondition (TExpr fallback) conds (TExpr e) =
TExpr (F.recodeWithCondition fallback (map untype conds) e)
where
untype (p, v) = (unTExpr . p . TExpr, v)
-- | Map values through a lookup table, with a default for misses.
recodeWithDefault ::
(Columnable a, Columnable b, Show (a, b)) =>
b -> [(a, b)] -> TExpr cols a -> TExpr cols b
recodeWithDefault d mapping (TExpr e) = TExpr (F.recodeWithDefault d mapping e)
-- | First element of a list column, or 'Nothing'.
firstOrNothing :: (Columnable a) => TExpr cols [a] -> TExpr cols (Maybe a)
firstOrNothing (TExpr e) = TExpr (F.firstOrNothing e)
-- | Last element of a list column, or 'Nothing'.
lastOrNothing :: (Columnable a) => TExpr cols [a] -> TExpr cols (Maybe a)
lastOrNothing (TExpr e) = TExpr (F.lastOrNothing e)
-- | Split text on a delimiter.
splitOn :: T.Text -> TExpr cols T.Text -> TExpr cols [T.Text]
splitOn delim (TExpr e) = TExpr (F.splitOn delim e)
-- | First regex match, or 'Nothing'.
match :: T.Text -> TExpr cols T.Text -> TExpr cols (Maybe T.Text)
match regex (TExpr e) = TExpr (F.match regex e)
-- | All regex matches.
matchAll :: T.Text -> TExpr cols T.Text -> TExpr cols [T.Text]
matchAll regex (TExpr e) = TExpr (F.matchAll regex e)
-- | Parse text into a time value with the given format.
parseDate ::
(ParseTime t, Columnable t) =>
T.Text -> TExpr cols T.Text -> TExpr cols (Maybe t)
parseDate format (TExpr e) = TExpr (F.parseDate format e)
-- | Number of days between two dates.
daysBetween :: TExpr cols Day -> TExpr cols Day -> TExpr cols Int
daysBetween (TExpr a) (TExpr b) = TExpr (F.daysBetween a b)
-- | Monadic bind over a column of monadic values.
bind ::
(Columnable a, Columnable (m a), Monad m, Columnable b, Columnable (m b)) =>
(a -> m b) -> TExpr cols (m a) -> TExpr cols (m b)
bind f (TExpr e) = TExpr (F.bind f e)