{-# LANGUAGE CPP #-}
{-# LANGUAGE OverloadedStrings #-}
module Graphics.Vega.VegaLite.Transform
( Operation(..)
, Window(..)
, WOperation(..)
, BinProperty(..)
, WindowProperty(..)
, ImputeProperty(..)
, ImMethod(..)
, aggregate_
, op_
, binned_
, impute_
, bin
, binProperty
, operationSpec
, windowTS
, joinAggregateTS
, imputeTS
) where
import qualified Data.Aeson as A
import qualified Data.Text as T
import Data.Aeson ((.=), object, toJSON)
import Data.Aeson.Types (Pair)
import Data.Maybe (mapMaybe)
#if !(MIN_VERSION_base(4, 12, 0))
import Data.Monoid ((<>))
#endif
import Graphics.Vega.VegaLite.Data
( DataValue
, DataValues
, dataValueSpec
, dataValuesSpecs
)
import Graphics.Vega.VegaLite.Foundation
( FieldName
, SortField
, sortFieldSpec
, fromT
, allowNull
)
import Graphics.Vega.VegaLite.Specification
( VLSpec
, TransformSpec(..)
, SelectionLabel
)
data Operation
= ArgMax (Maybe FieldName)
| ArgMin (Maybe FieldName)
| CI0
| CI1
| Count
| Distinct
| Max
| Mean
| Median
| Min
| Missing
| Product
| Q1
| Q3
| Stderr
| Stdev
| StdevP
| Sum
| Valid
| Variance
| VarianceP
operationSpec :: Operation -> VLSpec
operationSpec :: Operation -> VLSpec
operationSpec (ArgMax Maybe Text
Nothing) = VLSpec
"argmax"
operationSpec (ArgMax (Just Text
s)) = [Pair] -> VLSpec
object [Key
"argmax" forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv
.= Text
s]
operationSpec (ArgMin Maybe Text
Nothing) = VLSpec
"argmin"
operationSpec (ArgMin (Just Text
s)) = [Pair] -> VLSpec
object [Key
"argmin" forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv
.= Text
s]
operationSpec Operation
CI0 = VLSpec
"ci0"
operationSpec Operation
CI1 = VLSpec
"ci1"
operationSpec Operation
Count = VLSpec
"count"
operationSpec Operation
Distinct = VLSpec
"distinct"
operationSpec Operation
Max = VLSpec
"max"
operationSpec Operation
Mean = VLSpec
"mean"
operationSpec Operation
Median = VLSpec
"median"
operationSpec Operation
Min = VLSpec
"min"
operationSpec Operation
Missing = VLSpec
"missing"
operationSpec Operation
Product = VLSpec
"product"
operationSpec Operation
Q1 = VLSpec
"q1"
operationSpec Operation
Q3 = VLSpec
"q3"
operationSpec Operation
Stderr = VLSpec
"stderr"
operationSpec Operation
Stdev = VLSpec
"stdev"
operationSpec Operation
StdevP = VLSpec
"stdevp"
operationSpec Operation
Sum = VLSpec
"sum"
operationSpec Operation
Valid = VLSpec
"valid"
operationSpec Operation
Variance = VLSpec
"variance"
operationSpec Operation
VarianceP = VLSpec
"variancep"
aggregate_ :: Operation -> Pair
aggregate_ :: Operation -> Pair
aggregate_ Operation
op = Key
"aggregate" forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv
.= Operation -> VLSpec
operationSpec Operation
op
op_ :: Operation -> Pair
op_ :: Operation -> Pair
op_ Operation
op = Key
"op" forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv
.= Operation -> VLSpec
operationSpec Operation
op
data Window
= WAggregateOp Operation
| WOp WOperation
| WParam Int
| WField FieldName
windowFieldProperty :: Window -> Pair
windowFieldProperty :: Window -> Pair
windowFieldProperty (WAggregateOp Operation
op) = Key
"op" forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv
.= Operation -> VLSpec
operationSpec Operation
op
windowFieldProperty (WOp WOperation
op) = Key
"op" forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv
.= WOperation -> Text
wOperationLabel WOperation
op
windowFieldProperty (WParam Int
n) = Key
"param" forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv
.= Int
n
windowFieldProperty (WField Text
f) = Key
"field" forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv
.= Text
f
data WOperation
= RowNumber
| Rank
| DenseRank
| PercentRank
| CumeDist
| Ntile
| Lag
| Lead
| FirstValue
| LastValue
| NthValue
wOperationLabel :: WOperation -> T.Text
wOperationLabel :: WOperation -> Text
wOperationLabel WOperation
RowNumber = Text
"row_number"
wOperationLabel WOperation
Rank = Text
"rank"
wOperationLabel WOperation
DenseRank = Text
"dense_rank"
wOperationLabel WOperation
PercentRank = Text
"percent_rank"
wOperationLabel WOperation
CumeDist = Text
"cume_dist"
wOperationLabel WOperation
Ntile = Text
"ntile"
wOperationLabel WOperation
Lag = Text
"lag"
wOperationLabel WOperation
Lead = Text
"lead"
wOperationLabel WOperation
FirstValue = Text
"first_value"
wOperationLabel WOperation
LastValue = Text
"last_value"
wOperationLabel WOperation
NthValue = Text
"nth_value"
data BinProperty
= AlreadyBinned Bool
| BinAnchor Double
| Base Double
| Divide [Double]
| Extent Double Double
| MaxBins Int
| MinStep Double
| Nice Bool
| SelectionExtent SelectionLabel
| Step Double
| Steps [Double]
binProperty :: BinProperty -> Pair
binProperty :: BinProperty -> Pair
binProperty (AlreadyBinned Bool
b) = Key
"binned" forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv
.= Bool
b
binProperty (BinAnchor Double
x) = Key
"anchor" forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv
.= Double
x
binProperty (Base Double
x) = Key
"base" forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv
.= Double
x
binProperty (Divide [Double]
xs) = Key
"divide" forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv
.= [Double]
xs
binProperty (Extent Double
mn Double
mx) = Key
"extent" forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv
.= [ Double
mn, Double
mx ]
binProperty (SelectionExtent Text
s) = Key
"extent" forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv
.= [Pair] -> VLSpec
object [ Key
"selection" forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv
.= Text
s ]
binProperty (MaxBins Int
n) = Key
"maxbins" forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv
.= Int
n
binProperty (MinStep Double
x) = Key
"minstep" forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv
.= Double
x
binProperty (Nice Bool
b) = Key
"nice" forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv
.= Bool
b
binProperty (Step Double
x) = Key
"step" forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv
.= Double
x
binProperty (Steps [Double]
xs) = Key
"steps" forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv
.= [Double]
xs
bin :: [BinProperty] -> Pair
bin :: [BinProperty] -> Pair
bin [] = Key
"bin" forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv
.= Bool
True
bin [BinProperty]
xs = Key
"bin" forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv
.= [Pair] -> VLSpec
object (forall a b. (a -> b) -> [a] -> [b]
map BinProperty -> Pair
binProperty [BinProperty]
xs)
binned_ :: Pair
binned_ :: Pair
binned_ = Key
"bin" forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv
.= Text -> VLSpec
fromT Text
"binned"
data WindowProperty
= WFrame (Maybe Int) (Maybe Int)
| WIgnorePeers Bool
| WGroupBy [FieldName]
| WSort [SortField]
wpFrame , wpIgnorePeers, wpGroupBy, wpSort :: WindowProperty -> Maybe VLSpec
wpFrame :: WindowProperty -> Maybe VLSpec
wpFrame (WFrame Maybe Int
m1 Maybe Int
m2) = forall a. a -> Maybe a
Just (forall a. ToJSON a => a -> VLSpec
toJSON [Maybe Int -> VLSpec
allowNull Maybe Int
m1, Maybe Int -> VLSpec
allowNull Maybe Int
m2])
wpFrame WindowProperty
_ = forall a. Maybe a
Nothing
wpIgnorePeers :: WindowProperty -> Maybe VLSpec
wpIgnorePeers (WIgnorePeers Bool
b) = forall a. a -> Maybe a
Just (forall a. ToJSON a => a -> VLSpec
toJSON Bool
b)
wpIgnorePeers WindowProperty
_ = forall a. Maybe a
Nothing
wpGroupBy :: WindowProperty -> Maybe VLSpec
wpGroupBy (WGroupBy [Text]
fs) = forall a. a -> Maybe a
Just (forall a. ToJSON a => a -> VLSpec
toJSON [Text]
fs)
wpGroupBy WindowProperty
_ = forall a. Maybe a
Nothing
wpSort :: WindowProperty -> Maybe VLSpec
wpSort (WSort [SortField]
sfs) = forall a. a -> Maybe a
Just (forall a. ToJSON a => a -> VLSpec
toJSON (forall a b. (a -> b) -> [a] -> [b]
map SortField -> VLSpec
sortFieldSpec [SortField]
sfs))
wpSort WindowProperty
_ = forall a. Maybe a
Nothing
windowTS ::
[([Window], FieldName)]
-> [WindowProperty]
-> TransformSpec
windowTS :: [([Window], Text)] -> [WindowProperty] -> TransformSpec
windowTS [([Window], Text)]
wss [WindowProperty]
wps =
let addField :: Key -> (WindowProperty -> Maybe v) -> [a]
addField Key
n WindowProperty -> Maybe v
a = case forall a b. (a -> Maybe b) -> [a] -> [b]
mapMaybe WindowProperty -> Maybe v
a [WindowProperty]
wps of
[v
x] -> [Key
n forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv
.= v
x]
[v]
_ -> []
winFieldDef :: ([Window], v) -> VLSpec
winFieldDef ([Window]
ws, v
out) = [Pair] -> VLSpec
object (Key
"as" forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv
.= v
out forall a. a -> [a] -> [a]
: forall a b. (a -> b) -> [a] -> [b]
map Window -> Pair
windowFieldProperty [Window]
ws)
fields :: [Pair]
fields = [ Key
"window" forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv
.= forall a b. (a -> b) -> [a] -> [b]
map forall {v}. ToJSON v => ([Window], v) -> VLSpec
winFieldDef [([Window], Text)]
wss ]
forall a. Semigroup a => a -> a -> a
<> forall {a} {v}.
(KeyValue a, ToJSON v) =>
Key -> (WindowProperty -> Maybe v) -> [a]
addField Key
"frame" WindowProperty -> Maybe VLSpec
wpFrame
forall a. Semigroup a => a -> a -> a
<> forall {a} {v}.
(KeyValue a, ToJSON v) =>
Key -> (WindowProperty -> Maybe v) -> [a]
addField Key
"ignorePeers" WindowProperty -> Maybe VLSpec
wpIgnorePeers
forall a. Semigroup a => a -> a -> a
<> forall {a} {v}.
(KeyValue a, ToJSON v) =>
Key -> (WindowProperty -> Maybe v) -> [a]
addField Key
"groupby" WindowProperty -> Maybe VLSpec
wpGroupBy
forall a. Semigroup a => a -> a -> a
<> forall {a} {v}.
(KeyValue a, ToJSON v) =>
Key -> (WindowProperty -> Maybe v) -> [a]
addField Key
"sort" WindowProperty -> Maybe VLSpec
wpSort
in VLSpec -> TransformSpec
TS ([Pair] -> VLSpec
object [Pair]
fields)
joinAggregateTS :: [VLSpec] -> [WindowProperty] -> TransformSpec
joinAggregateTS :: [VLSpec] -> [WindowProperty] -> TransformSpec
joinAggregateTS [VLSpec]
ops [WindowProperty]
wps =
let addField :: Key -> (WindowProperty -> Maybe v) -> [a]
addField Key
n WindowProperty -> Maybe v
a = case forall a b. (a -> Maybe b) -> [a] -> [b]
mapMaybe WindowProperty -> Maybe v
a [WindowProperty]
wps of
[v
x] -> [Key
n forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv
.= v
x]
[v]
_ -> []
fields :: [Pair]
fields = [ Key
"joinaggregate" forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv
.= [VLSpec]
ops ]
forall a. Semigroup a => a -> a -> a
<> forall {a} {v}.
(KeyValue a, ToJSON v) =>
Key -> (WindowProperty -> Maybe v) -> [a]
addField Key
"frame" WindowProperty -> Maybe VLSpec
wpFrame
forall a. Semigroup a => a -> a -> a
<> forall {a} {v}.
(KeyValue a, ToJSON v) =>
Key -> (WindowProperty -> Maybe v) -> [a]
addField Key
"ignorePeers" WindowProperty -> Maybe VLSpec
wpIgnorePeers
forall a. Semigroup a => a -> a -> a
<> forall {a} {v}.
(KeyValue a, ToJSON v) =>
Key -> (WindowProperty -> Maybe v) -> [a]
addField Key
"groupby" WindowProperty -> Maybe VLSpec
wpGroupBy
forall a. Semigroup a => a -> a -> a
<> forall {a} {v}.
(KeyValue a, ToJSON v) =>
Key -> (WindowProperty -> Maybe v) -> [a]
addField Key
"sort" WindowProperty -> Maybe VLSpec
wpSort
in VLSpec -> TransformSpec
TS ([Pair] -> VLSpec
object [Pair]
fields)
data ImputeProperty
= ImFrame (Maybe Int) (Maybe Int)
| ImKeyVals DataValues
| ImKeyValSequence Double Double Double
| ImMethod ImMethod
| ImGroupBy [FieldName]
| ImNewValue DataValue
imputeProperty :: ImputeProperty -> Pair
imputeProperty :: ImputeProperty -> Pair
imputeProperty (ImFrame Maybe Int
m1 Maybe Int
m2) = Key
"frame" forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv
.= forall a b. (a -> b) -> [a] -> [b]
map Maybe Int -> VLSpec
allowNull [Maybe Int
m1, Maybe Int
m2]
imputeProperty (ImKeyVals DataValues
dVals) = Key
"keyvals" forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv
.= DataValues -> [VLSpec]
dataValuesSpecs DataValues
dVals
imputeProperty (ImKeyValSequence Double
start Double
stop Double
step) =
Key
"keyvals" forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv
.= [Pair] -> VLSpec
object [Key
"start" forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv
.= Double
start, Key
"stop" forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv
.= Double
stop, Key
"step" forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv
.= Double
step]
imputeProperty (ImMethod ImMethod
method) = Key
"method" forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv
.= ImMethod -> Text
imMethodLabel ImMethod
method
imputeProperty (ImNewValue DataValue
dVal) = Key
"value" forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv
.= DataValue -> VLSpec
dataValueSpec DataValue
dVal
imputeProperty (ImGroupBy [Text]
_) = Key
"groupby" forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv
.= VLSpec
A.Null
imputePropertySpecFrame, imputePropertySpecKeyVals,
imputePropertySpecKeyValSequence, imputePropertySpecGroupBy,
imputePropertySpecMethod, imputePropertySpecValue :: ImputeProperty -> Maybe VLSpec
imputePropertySpecFrame :: ImputeProperty -> Maybe VLSpec
imputePropertySpecFrame (ImFrame Maybe Int
m1 Maybe Int
m2) = forall a. a -> Maybe a
Just (forall a. ToJSON a => a -> VLSpec
toJSON (forall a b. (a -> b) -> [a] -> [b]
map Maybe Int -> VLSpec
allowNull [Maybe Int
m1, Maybe Int
m2]))
imputePropertySpecFrame ImputeProperty
_ = forall a. Maybe a
Nothing
imputePropertySpecKeyVals :: ImputeProperty -> Maybe VLSpec
imputePropertySpecKeyVals (ImKeyVals DataValues
dVals) = forall a. a -> Maybe a
Just (forall a. ToJSON a => a -> VLSpec
toJSON (DataValues -> [VLSpec]
dataValuesSpecs DataValues
dVals))
imputePropertySpecKeyVals ImputeProperty
_ = forall a. Maybe a
Nothing
imputePropertySpecKeyValSequence :: ImputeProperty -> Maybe VLSpec
imputePropertySpecKeyValSequence (ImKeyValSequence Double
start Double
stop Double
step) =
let obj :: [Pair]
obj = [Key
"start" forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv
.= Double
start, Key
"stop" forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv
.= Double
stop, Key
"step" forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv
.= Double
step]
in forall a. a -> Maybe a
Just ([Pair] -> VLSpec
object [Pair]
obj)
imputePropertySpecKeyValSequence ImputeProperty
_ = forall a. Maybe a
Nothing
imputePropertySpecGroupBy :: ImputeProperty -> Maybe VLSpec
imputePropertySpecGroupBy (ImGroupBy [Text]
fields) = forall a. a -> Maybe a
Just (forall a. ToJSON a => a -> VLSpec
toJSON [Text]
fields)
imputePropertySpecGroupBy ImputeProperty
_ = forall a. Maybe a
Nothing
imputePropertySpecMethod :: ImputeProperty -> Maybe VLSpec
imputePropertySpecMethod (ImMethod ImMethod
method) = forall a. a -> Maybe a
Just (forall a. ToJSON a => a -> VLSpec
toJSON (ImMethod -> Text
imMethodLabel ImMethod
method))
imputePropertySpecMethod ImputeProperty
_ = forall a. Maybe a
Nothing
imputePropertySpecValue :: ImputeProperty -> Maybe VLSpec
imputePropertySpecValue (ImNewValue DataValue
dVal) = forall a. a -> Maybe a
Just (DataValue -> VLSpec
dataValueSpec DataValue
dVal)
imputePropertySpecValue ImputeProperty
_ = forall a. Maybe a
Nothing
impute_ :: [ImputeProperty] -> Pair
impute_ :: [ImputeProperty] -> Pair
impute_ [ImputeProperty]
ips = Key
"impute" forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv
.= [Pair] -> VLSpec
object (forall a b. (a -> b) -> [a] -> [b]
map ImputeProperty -> Pair
imputeProperty [ImputeProperty]
ips)
imputeTS ::
FieldName
-> FieldName
-> [ImputeProperty]
-> TransformSpec
imputeTS :: Text -> Text -> [ImputeProperty] -> TransformSpec
imputeTS Text
field Text
key [ImputeProperty]
imProps =
let addField :: Key -> (ImputeProperty -> Maybe v) -> [a]
addField Key
n ImputeProperty -> Maybe v
a = case forall a b. (a -> Maybe b) -> [a] -> [b]
mapMaybe ImputeProperty -> Maybe v
a [ImputeProperty]
imProps of
[v
x] -> [Key
n forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv
.= v
x]
[v]
_ -> []
fields :: [Pair]
fields = [ Key
"impute" forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv
.= Text
field
, Key
"key" forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv
.= Text
key ]
forall a. Semigroup a => a -> a -> a
<> forall {a} {v}.
(KeyValue a, ToJSON v) =>
Key -> (ImputeProperty -> Maybe v) -> [a]
addField Key
"frame" ImputeProperty -> Maybe VLSpec
imputePropertySpecFrame
forall a. Semigroup a => a -> a -> a
<> forall {a} {v}.
(KeyValue a, ToJSON v) =>
Key -> (ImputeProperty -> Maybe v) -> [a]
addField Key
"keyvals" ImputeProperty -> Maybe VLSpec
imputePropertySpecKeyVals
forall a. Semigroup a => a -> a -> a
<> forall {a} {v}.
(KeyValue a, ToJSON v) =>
Key -> (ImputeProperty -> Maybe v) -> [a]
addField Key
"keyvals" ImputeProperty -> Maybe VLSpec
imputePropertySpecKeyValSequence
forall a. Semigroup a => a -> a -> a
<> forall {a} {v}.
(KeyValue a, ToJSON v) =>
Key -> (ImputeProperty -> Maybe v) -> [a]
addField Key
"method" ImputeProperty -> Maybe VLSpec
imputePropertySpecMethod
forall a. Semigroup a => a -> a -> a
<> forall {a} {v}.
(KeyValue a, ToJSON v) =>
Key -> (ImputeProperty -> Maybe v) -> [a]
addField Key
"groupby" ImputeProperty -> Maybe VLSpec
imputePropertySpecGroupBy
forall a. Semigroup a => a -> a -> a
<> forall {a} {v}.
(KeyValue a, ToJSON v) =>
Key -> (ImputeProperty -> Maybe v) -> [a]
addField Key
"value" ImputeProperty -> Maybe VLSpec
imputePropertySpecValue
in VLSpec -> TransformSpec
TS ([Pair] -> VLSpec
object [Pair]
fields)
data ImMethod
= ImMin
| ImMax
| ImMean
| ImMedian
| ImValue
imMethodLabel :: ImMethod -> T.Text
imMethodLabel :: ImMethod -> Text
imMethodLabel ImMethod
ImMin = Text
"min"
imMethodLabel ImMethod
ImMax = Text
"max"
imMethodLabel ImMethod
ImMean = Text
"mean"
imMethodLabel ImMethod
ImMedian = Text
"median"
imMethodLabel ImMethod
ImValue = Text
"value"