Skip to main content
cancel
Showing results for 
Search instead for 
Did you mean: 

Register now to learn Fabric in free live sessions led by the best Microsoft experts. From Apr 16 to May 9, in English and Spanish.

Reply
JoeJoe666
Frequent Visitor

Cycles Count

Hi,

I am new to power BI. I am not sure if I need to use DAX or M for what I need.

I would like create cycle count in new column based on the following:

*for every device

*change cycle when State reaches "1"

*every device gets its own cycle counts

*cycles increment by 1

*cycles must be in chronological order per "time", for every device

I tried the following without sucess:

Cycles = CALCULATE(DISTINCTCOUNT(Sheet2[State]),
FILTER(Sheet2,
Sheet2[Time]<EARLIER(Sheet2[Time]) &&
Sheet2[State]<2 &&
Sheet2[device]=EARLIER(Sheet2[device])))
 
Table name: "Sheet2"
Timedevicem1m2m3StateCycles
9/1/2020 0:014-0.103010011
9/1/2020 12:564-0.103010011
9/1/2020 13:264-0.103010011
9/1/2020 13:264-0.594010041
9/1/2020 13:314-0.594-0.110041
9/1/2020 13:364-0.654-1599.941
9/1/2020 20:3140.02-24.777.341
9/1/2020 20:33416.927077.831
9/1/2020 20:38417.4071.579.131
9/1/2020 20:58417.3317.384.431
9/1/2020 21:23417.28214.591.131
9/1/2020 21:27417.28415.992.431
9/1/2020 21:28415.92616.292.621
9/1/2020 23:2342.26925.6101.321
9/1/2020 23:4341.86226.4101.921
9/1/2020 23:444-0.1010012
9/2/2020 0:144-0.1010012
9/2/2020 7:194-0.102010012
9/2/2020 7:244-0.102010012
9/2/2020 7:264-0.175010042
9/2/2020 7:314-1.253-0.199.942
9/2/2020 20:014-0.025-579.742
9/2/2020 20:064-0.025-1579.742
9/2/2020 20:114-0.025-22.279.742
9/2/2020 20:1547.011080.132
9/2/2020 20:20417.4481.581.532
9/2/2020 20:35417.3765.985.532
9/2/2020 20:55417.34411.690.832
9/2/2020 20:58416.89712.591.622
9/2/2020 21:1849.27215.694.422
9/2/2020 23:0842.27422.6100.822
9/2/2020 23:1141.002010013
9/3/2020 9:354-0.102010013
9/3/2020 9:394-1.319010043
9/3/2020 9:494-0.661-0.199.943
9/3/2020 14:094-3.817-15.485.943
9/3/2020 20:344-0.294-33.269.643
9/3/2020 20:36417.005070.133
9/3/2020 21:21417.30513.18233
9/3/2020 21:56417.39823.291.333
9/3/2020 21:57415.34723.491.523
9/3/2020 22:5744.32230.898.323
9/4/2020 0:3242.24834.9102.123
9/4/2020 0:3440.622010014
9/4/2020 7:144-0.103010014
9/4/2020 7:184-0.716010044
9/4/2020 7:234-1.818-0.299.944
9/4/2020 12:234-7.451-793.644
9/4/2020 13:584-3.936-14.986.344
9/4/2020 18:484-0.704-26.975.344
9/4/2020 18:51411.033075.834
9/4/2020 19:16417.2687.382.534
9/4/2020 19:46417.22315.990.434
9/4/2020 19:51416.99417.291.624
9/4/2020 22:1142.24927.9101.424
9/4/2020 22:124-0.102010015
9/4/2020 23:524-0.104010015
9/1/2020 0:017-0.103010011
9/1/2020 12:567-0.103010011
9/1/2020 13:267-0.103010011
9/1/2020 13:267-0.594010041
9/1/2020 13:317-0.594-0.110041
9/1/2020 13:367-0.654-1599.941
9/1/2020 20:3170.02-24.777.341
9/1/2020 20:33716.927077.831
9/1/2020 20:38717.4071.579.131
9/1/2020 20:58717.3317.384.431
9/1/2020 21:23717.28214.591.131
9/1/2020 21:27717.28415.992.431
9/1/2020 21:28715.92616.292.621
9/1/2020 23:2372.26925.6101.321
9/1/2020 23:4371.86226.4101.921
9/1/2020 23:447-0.1010012
1 ACCEPTED SOLUTION
Greg_Deckler
Super User
Super User

@JoeJoe666 - Ah, you want Cthulhu - https://community.powerbi.com/t5/Quick-Measures-Gallery/Cthulhu/m-p/509739#M211

 

Actually, no, not Cthulhu but you can do it with 2 columns, I am still working on the single column version. PBIX is attached below sig, it is Table (13).

 

Cycle Change = 
    VAR __Table = FILTER('Table (13)',[device]=EARLIER([device]) && [time]<=EARLIER([Time]))
    VAR __Previous = MAXX(FILTER(__Table,[time]<EARLIER([Time])),[Time])
    VAR __PreviousState = MAXX(FILTER(__Table,[Time]=__Previous),[State])
RETURN
    IF(([State]=1 && __PreviousState<>1),1,0)


Cycles = SUMX(FILTER('Table (13)',[device]=EARLIER([device]) && [Time]<=EARLIER([Time])),[Cycle Change])

 

 

OK, got this into a single column:

Single Column non working = 
    VAR __BaseTable = 'Table (13)'
    VAR __Table = 
        ADDCOLUMNS(
            ADDCOLUMNS(
                ADDCOLUMNS(
                    FILTER(__BaseTable,[device]=EARLIER([device]) && [time]<=EARLIER([Time])),
                    "__Previous",MAXX(FILTER(__BaseTable,[time]<EARLIER([Time])),[Time])
                ),
                "__PreviousState",MAXX(FILTER(__BaseTable,[Time]=[__Previous]),[State])
            ),
            "__CycleChange",IF(([State]=1 && [__PreviousState]<>1),1,0)
        )
RETURN
    SUMX(__Table,[__CycleChange])

Updated the PBIX.


@ me in replies or I'll lose your thread!!!
Instead of a Kudo, please vote for this idea
Become an expert!: Enterprise DNA
External Tools: MSHGQM
YouTube Channel!: Microsoft Hates Greg
Latest book!:
The Definitive Guide to Power Query (M)

DAX is easy, CALCULATE makes DAX hard...

View solution in original post

11 REPLIES 11
Greg_Deckler
Super User
Super User

@JoeJoe666 - Just in case you missed it, I updated my original response with a DAX solution. Two column and single column solutions.


@ me in replies or I'll lose your thread!!!
Instead of a Kudo, please vote for this idea
Become an expert!: Enterprise DNA
External Tools: MSHGQM
YouTube Channel!: Microsoft Hates Greg
Latest book!:
The Definitive Guide to Power Query (M)

DAX is easy, CALCULATE makes DAX hard...
daxer-almighty
Solution Sage
Solution Sage

Here's the M code to do it:

let
    Source = Table.FromRows(Json.Document(Binary.Decompress(Binary.FromText("pZdbcqQwDEW3MsV34kjym62ksv9tjCw/iW0SOh80dMFBtnx1sT4/D4gfgB8EBP8ATsDj7TB8vINC0HwBfCDIrxxfbxcG6bTuKaNP+iNjo7kwZsNo/M6kgD9jQyhn5QIt/8ao4g4j6NFAASWIjPJ89l7pO6zddCqSLxNjKPBJ76BQIa8MJAhVGqKPMr8dZgdMy3jz2IJRZovhSbpjFNLc0Ei4iDfhmPMjJxdWUhjpPl4bJj8uC8+5ocylf7TkdB8nKXIpDll5HgFlmjvOtPmp4NJD5GR8iYt3nBl0PKmYGkGtwvAh4U+MAyG6+pkh8wIz1qS3U32tmF5fqMjqPq2hUiaOrj4DlGK9F/H6O8pNFP4CwzkYkajpJ9CWm14B1sUK0BS/Yqj5CtelCa0uQz7tMG07pn2aZ66TYG8xO2IiRkQRfITmHkuu1ZdTIYp7UK3nWl8zhydWLirylOtTwmX7WGP6hIpx2r2cqZRlHuaOayuHChYq1g3RRZGxJ3Kj/CXTKoxdQsrtqvwVY4aqdA6Xyp84NCc0TquAPmtYkhfsHkwKGUqa8qdMa1Gxi8rdgfUmawSg1rXvMp4hNmDskBYItQBi/jvKDqF0lJXNQ4zZfrdc+0xYlrHPnMmcLfqYOeqcUZrkoaynGJrbd8w0D9bU5Sglqo2knvWi8I6rS8BLTrO0zIT4q90vNjpLJnTGo5vkuGLah48lHOQFSSZXOU4cb946x3ZlRcYpp1E3Sc2U7vbBIo6ir3fMKQyubXVmMJxmnBrIBX9pE+jtLWibHtkKdM0jQ9XlZiieOMiRXHqybHaomeoKMyMmCaqbFmiblhXXx8hTivUFx8VUJ45V3FwuyVF2G77IEZurLrkq443V2Ynhlbsw5ob51hT4vYa3TcEjpmzw/8A8agouzO+bgoI9bQpkU/+8KfDHC02BP15qCgr2tCko2OOmoHEPmwJ/vNYU+OO1piAn8XlTUHU8qZj3OV//AQ==", BinaryEncoding.Base64), Compression.Deflate)), let _t = ((type nullable text) meta [Serialized.Text = true]) in type table [Time = _t, device = _t, m1 = _t, m2 = _t, m3 = _t, State = _t, Cycles = _t]),
    #"Changed Type" = Table.TransformColumnTypes(Source,{{"Time", type datetime}, {"device", Int64.Type}, {"m1", type number}, {"m2", type number}, {"m3", type number}, {"State", Int64.Type}, {"Cycles", Int64.Type}}),
    #"Removed Columns" = Table.RemoveColumns(#"Changed Type",{"Cycles"}),
    #"Sorted Rows" = Table.Sort(#"Removed Columns",{{"device", Order.Ascending}, {"Time", Order.Ascending}}),
    #"Added Index" = Table.AddIndexColumn(#"Sorted Rows", "Index", 0, 1, Int64.Type),
    #"Reordered Columns" = Table.ReorderColumns(#"Added Index",{"Index", "Time", "device", "m1", "m2", "m3", "State"}),
    #"Added Custom" = Table.AddColumn(#"Reordered Columns", "PrevState",
        each
            let
                PrevRowState = List.SingleOrDefault(
                    Table.SelectRows(#"Reordered Columns",
                        (r) => r[Index] = [Index] - 1 and r[device] = [device])[State],
                    null
                )
            in
                PrevRowState
    ),
    #"Added Custom1" = Table.AddColumn(#"Added Custom", "ShouldAddOne",
        each
            if [PrevState] is null or ([PrevState] <> 1 and [State] = 1)
            then 1 else 0
    ),
    #"Added Custom2" = Table.AddColumn(#"Added Custom1", "Cycle",
        each 
            // this is just a cumulative sum of ShouldAddOne
            List.Sum(
                Table.SelectRows(#"Added Custom1",
                    (r) => r[Index] <= [Index] and r[device] = [device]
                )[ShouldAddOne]
            )
    ),
    #"Removed Columns1" = Table.RemoveColumns(#"Added Custom2",{"PrevState", "ShouldAddOne"})
in
    #"Removed Columns1"

@daxer-almighty  Thank you. However, I am not sure how to even copy paste this into M. I will try to learn and try it. The DAX solution works but didn't work for me due to 400,000+ line items. Would this give me the same memory error?

@JoeJoe666 - Here is one improvement to the model that will hopefully help, I missed a filter. Let me see what other tricks I can do to get a more optimized calculation but try this in the mean time. There is a lot going on with this thing, it isn't pretty what you are trying to accomplish. For the Power Query solution, you open up Advanced Editor and paste in the code but it can be a little hairy if you have never done it before. Also, 2 column approach should be a lot less processing.

 

 

Cycles Count Column = 
    VAR __BaseTable = 'Table'
    VAR __Time = [Time]
    VAR __device = [device]
    VAR __Table = 
        ADDCOLUMNS(
            ADDCOLUMNS(
                ADDCOLUMNS(
                    FILTER(__BaseTable,[device]=__device && [time]<=__Time),
                    "__Previous",MAXX(FILTER(__BaseTable,[device]=__device && [time]<EARLIER([Time])),[Time])
                ),
                "__PreviousState",MAXX(FILTER(__BaseTable,[device]=__device && [Time]=[__Previous]),[State])
            ),
            "__CycleChange",IF(([State]=1 && [__PreviousState]<>1),1,0)
        )
RETURN
    SUMX(__Table,[__CycleChange])

 

 


@ me in replies or I'll lose your thread!!!
Instead of a Kudo, please vote for this idea
Become an expert!: Enterprise DNA
External Tools: MSHGQM
YouTube Channel!: Microsoft Hates Greg
Latest book!:
The Definitive Guide to Power Query (M)

DAX is easy, CALCULATE makes DAX hard...

@JoeJoe666 - OK here is another improvement I think that should run much faster

 

Cycles Count Column = 
    VAR __Time = [Time]
    VAR __device = [device]
    VAR __WorkingTable = FILTER('Table',[device]=__device && [time]<=__Time)
    VAR __Table = 
        ADDCOLUMNS(
            ADDCOLUMNS(
                ADDCOLUMNS(
                    __WorkingTable,
                    "__Previous",MAXX(FILTER(__WorkingTable,[time]<EARLIER([Time])),[Time])
                ),
                "__PreviousState",MAXX(FILTER(__WorkingTable,[Time]=[__Previous]),[State])
            ),
            "__CycleChange",IF(([State]=1 && [__PreviousState]<>1),1,0)
        )
RETURN
    SUMX(__Table,[__CycleChange])

 


@ me in replies or I'll lose your thread!!!
Instead of a Kudo, please vote for this idea
Become an expert!: Enterprise DNA
External Tools: MSHGQM
YouTube Channel!: Microsoft Hates Greg
Latest book!:
The Definitive Guide to Power Query (M)

DAX is easy, CALCULATE makes DAX hard...

tried the 2 column approach and 1st column not even coming back. same memory issue. 1 thing, my data always comes in chronological order for time column. Would it be less processing if [time]<EARLIER[time] is not required? my table is pre-sorted by time and device

@JoeJoe666 - Well, you could try adding an Index to the table in Power Query. Then you could use this:

1 column:

 

Cycles Count Column 1 = 
    VAR __Index = [Index]
    VAR __device = [device]
    VAR __WorkingTable = FILTER('Table',[device]=__device && [Index]<=__Index)
    VAR __Table = 
        ADDCOLUMNS(
            ADDCOLUMNS(
                ADDCOLUMNS(
                    __WorkingTable,
                    "__Previous",MAXX(FILTER(__WorkingTable,[time]<EARLIER([Time])),[Time])
                ),
                "__PreviousState",MAXX(FILTER(__WorkingTable,[Time]=[__Previous]),[State])
            ),
            "__CycleChange",IF(([State]=1 && [__PreviousState]<>1),1,0)
        )
RETURN
    SUMX(__Table,[__CycleChange])

 

2 column:

 

Cycle Change Step 1 = 
    VAR __Table = FILTER('Table',[device]=EARLIER([device]) && [Index]<=EARLIER([Index]))
    VAR __Previous = MAXX(FILTER(__Table,[Index]<EARLIER([Index])),[Index])
    VAR __PreviousState = MAXX(FILTER(__Table,[Index]=__Previous),[State])
RETURN
    IF(([State]=1 && __PreviousState<>1),1,0)



Cycles 2 = SUMX(FILTER('Table',[device]=EARLIER([device]) && [Index]<=EARLIER([Index])),[Cycle Change Step 1])

 

I'm working through another method.


@ me in replies or I'll lose your thread!!!
Instead of a Kudo, please vote for this idea
Become an expert!: Enterprise DNA
External Tools: MSHGQM
YouTube Channel!: Microsoft Hates Greg
Latest book!:
The Definitive Guide to Power Query (M)

DAX is easy, CALCULATE makes DAX hard...

@JoeJoe666 - OK, here is another method for the 2 step process that may perform better (should)

Cycle Change Step 1a = 
    VAR __device = [device]
    VAR __Index = [Index]
    VAR __Previous = CALCULATE(MAX([Index]),FILTER('Table',[device]=__device && [Index]<__Index))
    VAR __PreviousState = CALCULATE(MAX([State]),FILTER('Table',[Index]=__Previous))
RETURN
    IF(([State]=1 && __PreviousState<>1),1,0)


Cycles 2a = 
    VAR __device = [device]
    VAR __Index = [Index]
RETURN
    CALCULATE(SUM([Cycle Change Step 1a]), FILTER('Table',[device]=__device && [Index]<=__Index))

@ me in replies or I'll lose your thread!!!
Instead of a Kudo, please vote for this idea
Become an expert!: Enterprise DNA
External Tools: MSHGQM
YouTube Channel!: Microsoft Hates Greg
Latest book!:
The Definitive Guide to Power Query (M)

DAX is easy, CALCULATE makes DAX hard...

@JoeJoe666 - Just following up, did you ever get this operational?


@ me in replies or I'll lose your thread!!!
Instead of a Kudo, please vote for this idea
Become an expert!: Enterprise DNA
External Tools: MSHGQM
YouTube Channel!: Microsoft Hates Greg
Latest book!:
The Definitive Guide to Power Query (M)

DAX is easy, CALCULATE makes DAX hard...
Greg_Deckler
Super User
Super User

@JoeJoe666 - Ah, you want Cthulhu - https://community.powerbi.com/t5/Quick-Measures-Gallery/Cthulhu/m-p/509739#M211

 

Actually, no, not Cthulhu but you can do it with 2 columns, I am still working on the single column version. PBIX is attached below sig, it is Table (13).

 

Cycle Change = 
    VAR __Table = FILTER('Table (13)',[device]=EARLIER([device]) && [time]<=EARLIER([Time]))
    VAR __Previous = MAXX(FILTER(__Table,[time]<EARLIER([Time])),[Time])
    VAR __PreviousState = MAXX(FILTER(__Table,[Time]=__Previous),[State])
RETURN
    IF(([State]=1 && __PreviousState<>1),1,0)


Cycles = SUMX(FILTER('Table (13)',[device]=EARLIER([device]) && [Time]<=EARLIER([Time])),[Cycle Change])

 

 

OK, got this into a single column:

Single Column non working = 
    VAR __BaseTable = 'Table (13)'
    VAR __Table = 
        ADDCOLUMNS(
            ADDCOLUMNS(
                ADDCOLUMNS(
                    FILTER(__BaseTable,[device]=EARLIER([device]) && [time]<=EARLIER([Time])),
                    "__Previous",MAXX(FILTER(__BaseTable,[time]<EARLIER([Time])),[Time])
                ),
                "__PreviousState",MAXX(FILTER(__BaseTable,[Time]=[__Previous]),[State])
            ),
            "__CycleChange",IF(([State]=1 && [__PreviousState]<>1),1,0)
        )
RETURN
    SUMX(__Table,[__CycleChange])

Updated the PBIX.


@ me in replies or I'll lose your thread!!!
Instead of a Kudo, please vote for this idea
Become an expert!: Enterprise DNA
External Tools: MSHGQM
YouTube Channel!: Microsoft Hates Greg
Latest book!:
The Definitive Guide to Power Query (M)

DAX is easy, CALCULATE makes DAX hard...

@Greg_Deckler . Thank you so much. I would not have firgured this out at all.

My data has over 400,000 rows. I tried this and Power BI keeps saying "working on it" then 10-15 mins later says "There's not enough memory to complete this operation. Please try this later...." I have 32gb of memory.

Helpful resources

Announcements
Microsoft Fabric Learn Together

Microsoft Fabric Learn Together

Covering the world! 9:00-10:30 AM Sydney, 4:00-5:30 PM CET (Paris/Berlin), 7:00-8:30 PM Mexico City

PBI_APRIL_CAROUSEL1

Power BI Monthly Update - April 2024

Check out the April 2024 Power BI update to learn about new features.

April Fabric Community Update

Fabric Community Update - April 2024

Find out what's new and trending in the Fabric Community.