Forum Discussion
Poffarbacco
2 years agoFrequent Visitor
Calculating Current Value using Previous Row's Calculated Value
I have a dataset representing battery state changes, and I need to calculate the ResidualCapacity for each state change. The ResidualCapacity should be calculated as the previous ResidualCapacity plu...
- 2 years ago
Hi Poffarbacco
Here are some options (PBIX link here since forum attachment wasn't working):
1. DAX calculated column:
ResidualCapacity DAX = VAR UpperBound = 80 VAR CurrentState = 'Table'[ChangeState] VAR StateHistory = FILTER ( ALL ( 'Table'[ChangeState] ), 'Table'[ChangeState] <= CurrentState ) -- Cumulative ChargeVariation for all States up to and including current VAR CumulativeTable = ADDCOLUMNS ( StateHistory, "@Cumulative", VAR CurrentStateInner = 'Table'[ChangeState] RETURN CALCULATE ( SUM ( 'Table'[ChargeVariation] ), 'Table'[ChangeState] <= CurrentStateInner, REMOVEFILTERS ( 'Table' ) ) ) VAR MaxCumulative = MAXX ( CumulativeTable, [@Cumulative] ) VAR CurrentCumulative = SELECTCOLUMNS ( FILTER ( CumulativeTable, 'Table'[ChangeState] = CurrentState ), [@Cumulative] ) -- Adjustment required for largest exceedance of Threshold so far VAR Adjustment = MIN ( UpperBound - MaxCumulative, 0 ) VAR Result = CurrentCumulative + Adjustment RETURN Result2. Power Query
Adapt Imke Feldmann's Power Query function for adding a cumulative column from this post. (Shout out to ImkeF! )
Here is the modified version of the function that allows for nullable UpperBound and LowerBound parameters:
let func = ( Table as table, RunningTotalName as text, SortColumn as text, AmountColumn as text, UpperBound as nullable number, LowerBound as nullable number ) => let // Sort table and buffer it Sorted = Table.Buffer( Table.AddIndexColumn(Table.Sort(Table, {{SortColumn, Order.Ascending}}), "Index", 1, 1) ), // Select the Columns SelectColumns = Table.SelectColumns(Sorted, {SortColumn, AmountColumn, "Index"}), // Extract Amount column and buffer it ExtractAmountColumn = List.Buffer(Table.Column(SelectColumns, AmountColumn)), // Calculate a list with all running Totals RunningTotal = List.Skip( List.Generate( () => [ListItem = 0, Counter = 0], each [Counter] <= List.Count(ExtractAmountColumn), each [ ListItem = let Value = ExtractAmountColumn{[Counter]} + [ListItem] in List.Max({List.Min({Value, UpperBound}), LowerBound}), Counter = [Counter] + 1 ] ), 1 ), ConvertedTable = Table.FromList( RunningTotal, Splitter.SplitByNothing(), null, null, ExtraValues.Error ), ExpandedColumn = Table.ExpandRecordColumn( ConvertedTable, "Column1", {"ListItem", "Counter"}, {"ListItem", "Counter"} ), MergedQueries = Table.NestedJoin( Sorted, {"Index"}, ExpandedColumn, {"Counter"}, "Expanded Column1", JoinKind.LeftOuter ), Expand = Table.ExpandTableColumn( MergedQueries, "Expanded Column1", {"ListItem"}, {RunningTotalName} ), #"Removed Columns" = Table.RemoveColumns(Expand, {"Index"}), #"Changed Type" = Table.TransformColumnTypes( #"Removed Columns", {{RunningTotalName, type number}} ) in #"Changed Type" , documentation = [ Documentation.Name = " Table.ColumnRunningTotal", Documentation.Description = " Fast way to add running total to a table", Documentation.LongDescription = " Fast way to add running total to a table", Documentation.Category = " Table", Documentation.Source = " local", Documentation.Author = " Imke Feldmann: www.TheBIccountant.com", Documentation.Examples = {[Description = " ", Code = " ", Result = " "]} ] in Value.ReplaceType(func, Value.ReplaceMetadata(Value.Type(func), documentation))Applied to the table in the attached PBIX it looks like this:
let Source = Table.FromRows(Json.Document(Binary.Decompress(Binary.FromText("i45WMlTSUTI3gBCxOtFKRkCmrimQMDMF842BTCOQvAVE3gQkb4ikwRRZQywA", BinaryEncoding.Base64), Compression.Deflate)), let _t = ((type nullable text) meta [Serialized.Text = true]) in type table [ChangeState = _t, ChargeVariation = _t, #"ResidualCapacity Expected" = _t]), #"Changed Type" = Table.TransformColumnTypes(Source,{{"ChangeState", Int64.Type}, {"ChargeVariation", Int64.Type}, {"ResidualCapacity Expected", Int64.Type}}), #"Add Running Total" = ColumnRunningTotal(#"Changed Type", "ResidualCapacity PQ", "ChangeState", "ChargeVariation", 80, null) in #"Add Running Total"Were these the sort of thing you were looking for? 🙂
ImkeF
2 years agoCommunity Champion
Hi Poffarbacco ,
yes, Power Query would be more efficient.
Please check out my solution that OwenAuger mentioned above.
It did the trick for me.