dataframe-operations 2.2.0.0 → 2.3.0.0
raw patch · 6 files changed
+83/−14 lines, 6 filesdep ~dataframe-corePVP ok
version bump matches the API change (PVP)
Dependency ranges changed: dataframe-core
API changes (from Hackage documentation)
- DataFrame.Operations.Transformations: instance DataFrame.Internal.Column.Columnable a => DataFrame.Operations.Transformations.ImputeOp a
+ DataFrame.Functions: add :: (Num a, Columnable a) => Expr a -> Expr a -> Expr a
+ DataFrame.Functions: divide :: (Fractional a, Columnable a) => Expr a -> Expr a -> Expr a
+ DataFrame.Functions: isNotNull :: Columnable a => Expr (Maybe a) -> Expr Bool
+ DataFrame.Functions: isNull :: Columnable a => Expr (Maybe a) -> Expr Bool
+ DataFrame.Functions: mult :: (Num a, Columnable a) => Expr a -> Expr a -> Expr a
+ DataFrame.Functions: prettyPrint :: Expr a -> String
+ DataFrame.Functions: sub :: (Num a, Columnable a) => Expr a -> Expr a -> Expr a
+ DataFrame.Monad: [Asc] :: forall a. (Columnable a, Ord a) => Expr a -> SortOrder
+ DataFrame.Monad: [Desc] :: forall a. (Columnable a, Ord a) => Expr a -> SortOrder
+ DataFrame.Monad: data SortOrder
+ DataFrame.Monad: excludeM :: [Text] -> FrameM ()
+ DataFrame.Monad: selectM :: [Text] -> FrameM ()
+ DataFrame.Monad: sortByM :: [SortOrder] -> FrameM ()
+ DataFrame.Operations.Transformations: instance (DataFrame.Internal.Column.Columnable a, (TypeError ...)) => DataFrame.Operations.Transformations.ImputeOp a
Files
- dataframe-operations.cabal +2/−2
- src/DataFrame/Functions.hs +19/−1
- src/DataFrame/Monad.hs +17/−0
- src/DataFrame/Operations/Core.hs +2/−2
- src/DataFrame/Operations/Statistics.hs +1/−1
- src/DataFrame/Operations/Transformations.hs +42/−8
dataframe-operations.cabal view
@@ -1,6 +1,6 @@ cabal-version: 3.4 name: dataframe-operations-version: 2.2.0.0+version: 2.3.0.0 synopsis: Column operations, expression DSL, and statistics for the dataframe ecosystem. description: Untyped column operations (select, filter, sort, join, groupBy,@@ -58,7 +58,7 @@ build-depends: base >= 4 && < 5, bytestring >= 0.11 && < 0.14, containers >= 0.6.7 && < 0.10,- dataframe-core >= 2.2 && < 2.3,+ dataframe-core >= 2.3 && < 2.4, dataframe-parsing >= 2.2 && < 2.3, random >= 1.2 && < 2, regex-tdfa >= 1.3.0 && < 2,
src/DataFrame/Functions.hs view
@@ -11,7 +11,15 @@ {-# LANGUAGE TypeOperators #-} {-# LANGUAGE UndecidableInstances #-} -module DataFrame.Functions (module DataFrame.Functions, module DataFrame.Operators) where+module DataFrame.Functions (+ module DataFrame.Functions,+ module DataFrame.Operators,+ add,+ sub,+ mult,+ divide,+ prettyPrint,+) where import DataFrame.Internal.Column import DataFrame.Internal.Expression@@ -476,6 +484,16 @@ {-# SPECIALIZE isNothing :: Expr (Maybe Double) -> Expr Bool #-} {-# SPECIALIZE isNothing :: Expr (Maybe Int) -> Expr Bool #-} {-# INLINEABLE isNothing #-}++-- | SQL spelling of 'isNothing'.+isNull :: (Columnable a) => Expr (Maybe a) -> Expr Bool+isNull = isNothing+{-# INLINEABLE isNull #-}++-- | SQL spelling of 'isJust'.+isNotNull :: (Columnable a) => Expr (Maybe a) -> Expr Bool+isNotNull = isJust+{-# INLINEABLE isNotNull #-} fromJust :: (Columnable a) => Expr (Maybe a) -> Expr a fromJust = liftDecorated Maybe.fromJust "fromJust" Nothing
src/DataFrame/Monad.hs view
@@ -24,6 +24,10 @@ sampleM, takeM, dropM,+ selectM,+ excludeM,+ sortByM,+ SortOrder (..), columnAsListM, filterJustM, imputeM,@@ -43,6 +47,8 @@ import DataFrame.Internal.Expression (Expr (..), UExpr (..), prettyPrint) import DataFrame.Internal.Nullable (BaseType) import qualified DataFrame.Operations.Core as D+import DataFrame.Operations.Permutation (SortOrder)+import qualified DataFrame.Operations.Permutation as D import qualified DataFrame.Operations.Subset as D import DataFrame.Operations.Transformations (ImputeOp) import qualified DataFrame.Operations.Transformations as D@@ -110,6 +116,17 @@ dropM :: Int -> FrameM () dropM n = modifyM (D.drop n)++-- | Keep only the named columns. 'dropM' drops rows; this drops columns.+selectM :: [T.Text] -> FrameM ()+selectM names = modifyM (D.select names)++-- | Drop the named columns.+excludeM :: [T.Text] -> FrameM ()+excludeM names = modifyM (D.exclude names)++sortByM :: [SortOrder] -> FrameM ()+sortByM orders = modifyM (D.sortBy orders) columnAsListM :: (Columnable a) => Expr a -> FrameM [a] columnAsListM c = inspectM (D.columnAsList c)
src/DataFrame/Operations/Core.hs view
@@ -665,9 +665,9 @@ fromRows :: [T.Text] -> [[Any]] -> DataFrame fromRows names rows = L.foldl'- (\df i -> insertColumn (names !! i) (mkColumnFromRow i rows) df)+ (\df (i, name) -> insertColumn name (mkColumnFromRow name i rows) df) empty- [0 .. length names - 1]+ (zip [0 ..] names) {- | O (k * n) Counts the occurences of each value in a given column.
src/DataFrame/Operations/Statistics.hs view
@@ -327,7 +327,7 @@ if all (== h) (toList @b value) then imputeCore col h df else error "Impute expression returned more than one value"- runImputeWith _ _ df = df+ runImputeWith _ expr _ = throw (NonColumnReferenceException (T.pack (show expr))) imputeWith :: forall a.
src/DataFrame/Operations/Transformations.hs view
@@ -1,5 +1,5 @@ {-# LANGUAGE ConstrainedClassMethods #-}-{-# LANGUAGE ExplicitNamespaces #-}+{-# LANGUAGE DataKinds #-} {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE GADTs #-}@@ -7,6 +7,7 @@ {-# LANGUAGE RankNTypes #-} {-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE TypeApplications #-}+{-# LANGUAGE TypeOperators #-} {-# LANGUAGE UndecidableInstances #-} {-# LANGUAGE UndecidableSuperClasses #-} @@ -40,8 +41,10 @@ import Data.Maybe import DataFrame.Errors (DataFrameException (..), TypeErrorContext (..)) import DataFrame.Internal.Column (+ Column, Columnable, TypedColumn (..),+ columnTypeString, hasMissing, ifoldrColumn, imapColumn,@@ -52,6 +55,8 @@ import DataFrame.Internal.Interpreter import DataFrame.Internal.Nullable (BaseType) import DataFrame.Operations.Core+import GHC.TypeLits (ErrorMessage (..), TypeError)+import Type.Reflection (typeRep) -- | O(k) Apply a function to a given column in a dataframe. apply ::@@ -218,7 +223,9 @@ Left e -> throw e Right column' -> insertColumn columnName column' df --- | Core impute implementation for nullable columns. Silently no-ops on non-nullable columns.+{- | Core impute implementation for nullable columns. A column with no null+bitmap cannot hold a missing value, so imputing it is a mistake, not a no-op.+-} imputeCore :: forall b. (Columnable b) =>@@ -234,9 +241,24 @@ Left (TypeMismatchException context) -> throw $ TypeMismatchException (context{callingFunctionName = Just "impute"}) Left exception -> throw exception Right res -> res- _ -> df-imputeCore _ _ df = df+ Just col ->+ throw+ (nonNullableColumnError columnName ("Maybe " ++ show (typeRep @b)) col)+imputeCore expr _ _ = throw (NonColumnReferenceException (T.pack (show expr))) +{- | 'impute' was handed a column that carries no null bitmap, so there is+nothing it could replace.+-}+nonNullableColumnError :: T.Text -> String -> Column -> DataFrameException+nonNullableColumnError columnName wanted col =+ TypeMismatchException @() @()+ MkTypeErrorContext+ { userType = Left wanted+ , expectedType = Left (columnTypeString col)+ , errorColumnName = Just (T.unpack columnName)+ , callingFunctionName = Just "impute"+ }+ class (Columnable a) => ImputeOp a where runImpute :: Expr a -> BaseType a -> DataFrame -> DataFrame runImputeWith ::@@ -246,12 +268,24 @@ DataFrame -> DataFrame -instance {-# OVERLAPPABLE #-} (Columnable a) => ImputeOp a where- runImpute _ _ df = df- runImputeWith _ _ df = df+instance+ {-# OVERLAPPABLE #-}+ ( Columnable a+ , TypeError+ ( 'Text "impute needs a nullable column, but was given Expr "+ ':<>: 'ShowType a+ ':$$: 'Text "Try F.col @(Maybe "+ ':<>: 'ShowType a+ ':<>: 'Text ") instead."+ )+ ) =>+ ImputeOp a+ where+ runImpute = errorWithoutStackTrace "impute: unreachable"+ runImputeWith = errorWithoutStackTrace "impute: unreachable" {- | Replace all instances of `Nothing` in a column with the given value.-When the column is already non-nullable, this is a silent no-op.+Throws when the column carries no nulls to replace. -} impute :: forall a.