Map state transitions with Deedle

93 Views Asked by At

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    
1

There are 1 best solutions below

0
jim108dev On BEST ANSWER

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       

Related Questions in F#