Suppose I have a table with products and events (processing steps), like
type Event = | E1 | E2
let events = Series.ofValues [ E1;E2;E2 ]
let products = Series.ofValues [ "A";"A";"B"]
let df = Frame(["Product"; "Event"], [products; events])
df.Print()
Product Event
0 -> A E1
1 -> A E2
2 -> B E2
and a transition function which determines a new state given the old state and the event
type State = S0 | S1 | S2
let evolve (s:State) (e:Event) :State =
match s,e with
| _, E1 -> S1
| S0, E2 -> S0
| _, E2 -> S2
How can the state transitions be mapped? The result should be something like
let stateTransitions = df |> ???
stateTransitions.Print()
Product Event NewState
0 -> A E1 S1
1 -> A E2 S2
2 -> B E2 S0
Update: I know how to get the final state of every product but the aggregate function does not show the transitions.
let finalStates =
df
|> Frame.aggregateRowsBy ["Product"] ["Event"]
(fun s -> s.Values |> Seq.fold evolve S0)
finalStates.Print()
Product Event
0 -> A S2
1 -> B S0
I guess there is no existing function. I did grouping/nesting by product, fold with storing all states and build a new series/column of the results, unnest.
let stateTransitions =
df
|> Frame.groupRowsByString "Product"
|> Frame.nest
|> Series.mapValues (fun nf ->
let events = nf.Columns.["Event"].As<Event>()
let values' =
events.Values
|> Seq.fold (fun acc e ->
let s = acc |> List.head
let s' = evolve s e
s'::acc) [S0]
|> Seq.rev
|> Seq.tail
let states' =
Seq.zip events.Keys values'
|> Series.ofObservations
nf.AddColumn("NewState", states')
nf
)
|> Frame.unnest
|> Frame.indexRowsOrdinally
stateTransitions.Print()
Product Event NewState
0 -> A E1 S1
1 -> A E2 S2
2 -> B E2 S0