Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

DAX get N'th last non-blank value

Tags:

powerbi

dax

For any given date, I would like to get an average Sales of the most recent 3 days with non-blank sales. So I need to retrieve not only the last non-blank sales (which might be easy) but I also need to get the second last and third last sales. Generally, I need N'th last sales.

Sample data:


+------------+--------+--------+--------+--------+------------------+
|    Date    | Amount | N'th 1 | N'th 2 | N'th 3 | Expected Results |
+------------+--------+--------+--------+--------+------------------+
| 2021-02-01 |      1 |      1 |        |        |             1.00 |
| 2021-02-02 |      2 |      2 |      1 |        |             1.50 |
| 2021-02-03 |      2 |      2 |      2 |      1 |             1.67 |
| 2021-02-04 |        |      2 |      2 |      1 |             1.67 |
| 2021-02-05 |      3 |      3 |      2 |      2 |             2.33 |
| 2021-02-06 |        |      3 |      2 |      2 |             2.33 |
| 2021-02-07 |        |      3 |      2 |      2 |             2.33 |
| 2021-02-08 |      4 |      4 |      3 |      2 |             3.00 |
| 2021-02-09 |        |      4 |      3 |      2 |             3.00 |
| 2021-02-10 |        |      4 |      3 |      2 |             3.00 |
| 2021-02-11 |        |      4 |      3 |      2 |             3.00 |
+------------+--------+--------+--------+--------+------------------+

The N'th 1 is the last "non-blank" sales. The N'th 2 is the "last but one". The expected result is the average of N1, N2, N3.

Link to sample data file with solutions suggested by accepted answer:
DAX Rolling Average NonBlanks.pbix

like image 953
Przemyslaw Remin Avatar asked Feb 09 '21 15:02

Przemyslaw Remin


People also ask

How do I filter blank values in DAX?

The proper way to filter for blanks in this case is to use the ISBLANK() function. Conversely, if you want to exclude only blanks, you wouldn't write <>BLANK() in your filter, but you'd use the NOT operator.

How do I count non blank rows in DAX?

The COUNTAX function counts non-blank results when evaluating the result of an expression over a table. That is, it works just like the COUNTA function, but is used to iterate through the rows in a table and count rows where the specified expressions results in a non-blank result.

Is not equal to blank in DAX?

The “not equal to” operator <> returns TRUE when the two arguments do not have the same value. A comparison between BLANK and 0 or between BLANK and an empty string returns FALSE. Use the == operator to treat BLANK and 0 or empty string as different values.

How do you replace blank values with 0 in DAX?

If you want is to replace blank or null values with 0 without creating a new column, then use the Query Editor. Select Edit Query. In the query window, right click on the column header and select Replace Values...

What is the use of last blank in Dax?

LASTNONBLANK DAX Function (Time Intelligence) Context Transition. Returns the last value in the column for which the expression has a non blank value. LASTNONBLANK ( <ColumnName>, <Expression> ) The source values. The expression to be evaluated for each value.

What is the last non-blank value of <expression>?

The last non-blank value of <expression> corresponding to the sorted values of <column>. A reference to any column. A table with a single column.

What happens when lastnonblank is executed in Dax?

When LASTNONBLANK is executed providing a column reference as the first argument, DAX implicitly rewrites the expression by retrieving the values using DISTINCT in a potential context transition. The previous code is internally rewritten as:

What is the use of firstnonblank function in Dax?

The DAX functions FIRSTNONBLANK, FIRSTNONBLANKVALUE, LASTNONBLANK, and LASTNONBLANKVALUE are iterators that could materialize data at the granularity of the column provided as a first argument.


1 Answers

Here's my take (it's a measure):

Non-blank average = 
var curDate = SELECTEDVALUE(Data[Date], MAX(Data[Date]))
var nonBlankTab = FILTER(ALL(Data), NOT(ISBLANK(Data[Amount])) && Data[Date] <= curDate)
var rankedTab = FILTER ( ADDCOLUMNS ( nonBlankTab, "Rank", RANKX ( nonBlankTab, [Date] ) ), [Rank] <= 3 )
return AVERAGEX(rankedTab, [Amount])

EDIT:

Just an explanation:

  • the measure is calculated for the selected date. If no date context is present, the latest date is assumed.
  • Then I filter out the table to contain only rows with non blank sales not later than curDate
  • Then I rank the dates so that the latest 3 dates always receive ranks 1, 2 and 3.
  • Then I filter out all the dates with rank higher than 3
  • Finally, I calculate an average over the remaining 3 data points.

enter image description here

EDIT2:

I simplified the measure a bit - lastSalesDate is not necessary. Also, as per request in the comments, I left the first attempt as it was, and here is the modified version with TOPN instead of ADDCOLUMNS/RANKX/FILTER combo:

Non-blank average = 
var curDate = SELECTEDVALUE(Data[Date], MAX(Data[Date]))
var nonBlankTab = FILTER(ALL(Data), NOT(ISBLANK(Data[Amount])) && Data[Date] <= curDate)
var rankedTab = TOPN(3, nonBlankTab, [Date])
return AVERAGEX(rankedTab, [Amount])

EDIT3:

A more universal version of the measure that just removes filters from Date column, which is actually all we need. No need to butcher all the other filters on the table:

Non-blank average = 
var curDate = SELECTEDVALUE(Data[Date], MAX(Data[Date]))
var nonBlankTab = CALCULATETABLE(FILTER(Data, NOT(ISBLANK(Data[Amount])) && Data[Date] <= curDate), REMOVEFILTERS(Data[Date]))
var rankedTab = TOPN(3, nonBlankTab, [Date])
return AVERAGEX(rankedTab, [Amount])
like image 55
W.B. Avatar answered Sep 30 '22 13:09

W.B.