Power BI Dax to Calculate the average in 3 periods - powerbi

I have two below tables in Dim_Date the Period doesn't correspond to exact months and first I calculated a measure to Divide the count of records per region by NumofWeeks.
The Num of the week is always the same in the same period.
Table1
Region
Subregion
DataID
Amount
North Central
Missouri
12042022
123000
North Central
Minnesota
12052022
170000
North Central
North Dakota
10042022
234000
Northeast
New York
08042022
500000
Northeast
New Jersey
12052022
578000
Southwest
Nevada
12032022
679000
Southwest
Arizona
10032022
654000
DimDate
DataID
Period
NumofWeeks
12052022
2022_05
5
10042022
2022_04
4
12042022
2022_04
4
12052022
2022_05
5
08042022
2022_04
4
12032022
2022_03
4
10032022
2022_03
4
Divide per region week =
VAR TotalCountPerRegion = COUNT(Table1[Region])
VAR tblNumOfWeeksInPeriod=
SUMMARIZE(
DimDate
,DimDate[Period]
,DimDate[NumofWeeks]
)
VAR SuMOfWeeksInPeriod = SUMX(tblNumOfWeeksInPeriod,DimDate[NumofWeeks])
RETURN
MROUND(
DIVIDE(
TotalCountPerRegion
,SuMOfWeeksInPeriod
)
,1
)
With the formula, I got the following table
Period
Divide per region week
2021_04
17
2021_05
15
2021_06
9
2021_07
16
2021_08
20
2021_09
21
2021_10
17
2021_11
19
2021_12
20
2022_01
27
I want a new formula to calculate the average of the period with 2 following periods
Example
Average 2021_04 = 2021_04 + 2021_05 + 2021_06 = (17+15+9)/3
Average 2021_05 = 2021_05 + 2021_06 + 2021_07 = (15+9+16)/3
and so on.
thank you in advance.

I accepted this solution thank you very much ...
[M 3-Period Rolling Avg] =
// Set the number of periods to calculate
// the average over.
var PeriodCount = 3
// First, get the last visible period.
var LastPeriodSeqno = MAX( Dim_Date[PeriodSeqno] )
// Then, get the periods over which to calc.
var PeriodsToAverageOver =
CALCULATETABLE(
DISTINCT( Dim_Date[PeriodSeqno] ),
// Here's the place where you use the fact that
// all the periods are consecutively numbered.
// In fact, the counting does not have to start
// at 1 but it has to increment by 1.
Dim_Date[PeriodSeqno] <= LastPeriodSeqno,
Dim_Date[PeriodSeqno] > LastPeriodSeqno - PeriodCount,
REMOVEFILTERS( Dim_Date )
)
// We need to make sure that there are indeed
// PeriodCount periods in the set. Otherwise,
// the average will not be correct. This could happen
// if we were too close to the beginning of the calendar.
var ShouldCalculate =
COUNTROWS( PeriodsToAverageOver ) = PeriodCount
var Result =
if( ShouldCalculate,
CALCULATE(
AVERAGEX(
PeriodsToAverageOver,
[M]
),
REMOVEFILTERS( Dim_Date )
)
)
return
Result

My calendar is different for example the periods are like a financial calendar the period
2021_04 - Starts on 05/04/2021 and finishes on 02/05/2021
2021_05 - Starts on 03/05/2021 and finishes on 30/05/2021
2021_06 - Starts on 31/05/2021 and finishes on 04/07/2021
I want to calculate
Divide per region week =
VAR TotalCountPerRegion = COUNT(Table1[Region])
VAR tblNumOfWeeksInPeriod=
SUMMARIZE(
DimDate
,DimDate[Period]
,DimDate[NumofWeeks]
)
VAR SuMOfWeeksInPeriod = SUMX(tblNumOfWeeksInPeriod,DimDate[NumofWeeks])
RETURN
MROUND(
DIVIDE(
TotalCountPerRegion
,SuMOfWeeksInPeriod
)
,1
)
Rolling 3 periods if we start in 2021_04 I have
2021_06 = Average(2021_06+2021_05+2021_04)
2021_07 = Average(2021_07+2021_06+2021_05)
2021_08 = Average(2021_08+2021_07+2021_06)
and so on
I need to incorporate the formula above because the average is the sum of the formula for 3 periods.
Thanks in advance

Related

PowerBI: Count email subjects by month - assign subject to the month it first appeared

I have a dataset similar to the following:
Email Subject
Date Received
Month Year received
Red
1 Jan 21
Jan 21
Blue
1 Jan 21
Jan 21
Green
3 Feb 21
Feb 21
Red
5 Feb 21
Feb 21
What I am looking for is a count of distinct email subjects by month however if a subject appears in the previous month then don't count it.
The ideal outcome using the data above would be a:
Total count (No month breakdown) = 3 ( 3 unique subjects - Red, Blue & Green)
Count of subjects for Jan = 2 (Red and Blue)
Count of subjects for Feb = 1 (Only green because Red appeared in the previous month)
This is so I can count how many email threads were received each month without duplicating a thread that spanned over multiple months.
Any help would be greatly appreciated - been stuck for ages!
Assuming you have no date table (if you do, you can adjust the code accordingly), here you go.
Measure =
VAR month = MONTH(MAX('Table'[Date Received]))
VAR year = YEAR(MAX('Table'[Date Received]))
VAR ddate = MAX('Table'[Date Received])
VAR currentTable =
CALCULATETABLE(VALUES('Table'[Email Subject]),
FILTER(ALL('Table'),
MONTH('Table'[Date Received]) = month && YEAR('Table'[Date Received]) = year)
)
VAR excludeTable =
CALCULATETABLE(VALUES('Table'[Email Subject]),
FILTER(ALL('Table'),
'Table'[Date Received] < EOMONTH(ddate,-1))
)
VAR result = EXCEPT( currentTable,excludeTable)
RETURN IF(HASONEVALUE('Table'[Email Subject]),COUNTROWS(result),DISTINCTCOUNT('Table'[Email Subject]))
You can use a measure like this
Measure =
VAR mxp =
MAX ( 'Fact'[Month Year received] )
VAR _cp =
CALCULATETABLE (
VALUES ( 'Fact'[Email Subject] ),
'Fact'[Month Year received] = mxp
)
VAR _ytd =
CALCULATETABLE (
VALUES ( 'Fact'[Email Subject] ),
'Fact'[Month Year received] < mxp
)
VAR _join =
COUNTX ( EXCEPT ( _cp, _ytd ), [Email Subject] )
RETURN
IF (
HASONEVALUE ( 'Fact'[Month Year received] ),
_join,
COUNTROWS ( VALUES ( 'Fact'[Email Subject] ) )
)
mxp gets what is currently visible to DAX
'Fact'[Month Year received] = mxp gets only the current month's unique email subjects.
'Fact'[Month Year received] < mxp gets anything up-to immediately preceding to whatever is currently visible
_join does a left-anti join that brings whatever unique is visible in the current month.
subtotal are handled little differently through IF(HASONEVALUE('Fact'[Month Year received]),_join,COUNTROWS(VALUES('Fact'[Email Subject])))

Power BI - Get date when sum is 0

I have two tables - Customer and Transaction. The transaction holds invoices and payments. I need to get the date when the transaction sum is 0 or grater.
So the expected result should be John 02-20-2021. How can I achieve this?
customerID
Name
1
John
2
Ben
customerID
value
date
1
-150
02-13-2021
1
100
02-14-2021
1
200
02-20-2021
1
10
02-23-2021
You can try this out, by adding some new measures.
First measure to calculate the account balance over dates, returning a value only for positive balance:
Account Balance :=
VAR _date = MAX ( Transaction[date] )
VAR _balance =
CALCULATE (
SUM ( Transaction[value] ) ,
Transaction[date] <= _date
)
RETURN
IF ( _balance >= 0 , _balance )
The second filters the original table based on this measure and returns the earliest date:
Break Even Date :=
MINX (
FILTER (
VALUES ( Transaction[date] ),
[Account Balance]
),
[date]
)
Result:
Do note that I have not tested this beyond your (simple) example.

Calculating a Moving Average for 3 months without blank values in DAX Power BI

I have Client Services table with [Billable Minutes] value.
I need to create [Moving Average for 3 months] measure, where the calculation will
only happen - if there are values in all 3 months in [Billable Minutes] exist !
(See below)
If [Billable Minutes] value is blank in at least one month in my Client Services table, then I want [Moving Avg] will show 0 or blank!
My goal:
Client Services table: Result:
Period [Billable Minutes] Period [Moving Avg]
2018-11 200 2019-01 200
2018-12 300
2019-01 100
To reach my goal, I am using the following DAX expression for [Moving Avg 3 months]:
Moving Avg 3 month =
VAR PeriodToUse = DATESINPERIOD('Calendar FY'[Date], LASTDATE('Calendar FY'[Date]), -3, MONTH)
VAR Result = CALCULATE(DIVIDE([Billable Minutes], COUNTROWS ('Calendar FY')), PeriodToUse)
VAR ZeroValue=IF(Minx('Client Services',[Billable Minutes])=0,0,Result)
Return Result
But, unfortunately, my end result is:
Client Services table: Result:
Period [Billable Minutes] Period [Moving Avg]
2018-11 200 2018-11 67
2018-12 300 2018-12 167
2019-01 100 2019-01 200
So, it takes an existing values in Client Services table and divides them by the number of periods.
For example for 2018-11, 2018-10, 2018-09 - it takes (200+0+0)/3=66.6 (67 rounded)
But I need the Moving Avg would be empty for 2018-11, because there are no values for 2018-10, 2018-09 in the Client Services table (same - for 2018-12, should not calculate)
Please, HELP!
Updated:
Here is the solution for this (thx to the answer below)
In order to check if there zero in the selected period, extra measures should be created:
Billable Minutes
Moving Avg Prev Month = Calculate('Client Services'[Billable Minutes],
PREVIOUSMONTH('Calendar FY'[Date]))
Billable Minutes
Moving Avg 2nd Prev Month = Calculate
('Client Services'[Billable Minutes Prev Month],
PREVIOUSMONTH('Calendar FY'[Date]))
Then, when you check whether there are zero values - you need to check it - not
just for [Billable Minutes], but for [Billable Minutes] within 3 months period =
within
[Billable Minutes]+[Billable Minutes Prev Month]+
[Billable Minutes 2nd Prev Month]
See the updated below (worked perfect):
enter
Billable Minutes 3 Months Avg =
VAR PeriodToUse = DATESINPERIOD('Calendar FY'[Date],
LASTDATE('Calendar FY'[Date]), -3, MONTH)
VAR Result = CALCULATE(DIVIDE([Billable Minutes],
COUNTROWS ('Calendar FY')), PeriodToUse)
VAR NMonthsPeriodBlank =
if([Billable Minutes] = BLANK(),0,1) +
if([Billable Minutes Prev Month] = BLANK(),0,1) +
if([Billable Minutes 2nd Prev Month] = BLANK(),0,1)
RETURN IF(NMonthsPeriodBlank < 3, BLANK(), Result)
Follow these below steps-
Step-1: Convert your Period column to Date considering 1st date of each month as below-
Step-2: Get back to report by clicking Close & Apply and create this below 4 measures-
total = SUM('Client Services'[Billable Minutes])
total prev = CALCULATE([total],PREVIOUSMONTH('Client Services'[Period]))
total second prev = CALCULATE([total prev],PREVIOUSMONTH('Client Services'[Period]))
3 month avergae =
VAR devide_by = if([total] = BLANK(),0,1) + if([total prev] = BLANK(),0,1) + if([total second prev] = BLANK(),0,1)
VAR total_amount = [total] + [total prev] + [total second prev]
RETURN IF(
devide_by < 3,
BLANK(),
total_amount/devide_by
)
Here is the final output-
====================
Solution in single measure
====================
You can convert all measures into 1 measure as below-
3 month average new =
VAR this_month = SUM('Client Services'[Billable Minutes])
VAR prev_month =
CALCULATE(
SUM('Client Services'[Billable Minutes]),
PREVIOUSMONTH('Client Services'[Period])
)
VAR second_prev_month =
CALCULATE(
SUM('Client Services'[Billable Minutes]),
PREVIOUSMONTH(
DATEADD(
'Client Services'[Period],
-1,
MONTH
)
)
)
VAR devide_by =
if(this_month = BLANK(),0,1) +
if(prev_month = BLANK(),0,1) +
if(second_prev_month = BLANK(),0,1)
VAR total_amount = this_month + prev_month + second_prev_month
RETURN IF(
devide_by < 3,
BLANK(),
total_amount/devide_by
)

Sum row with next row value and grab next value in other column for the date selected

Let's say I have this data:
Earn Earn Cum.
13-Apr - -
14-Apr 48 48
15-Apr 257 305
16-Apr 518 823
17-Apr 489 1,312
18-Apr 837 2,149
19-Apr 1,005 3,154
20-Apr 1,021 4,175
21-Apr 1,463 5,638
22-Apr 2,630 8,268
23-Apr 2,993 11,261
24-Apr 3,354 14,615
25-Apr 4,332 18,947
26-Apr 4,885 23,832
27-Apr 4,514 28,346
28-Apr 4,356 32,702
29-Apr 4,824 37,526
30-Apr 7,082 44,608
1-May 6,091 50,699
2-May 1,407 52,106
When a date is selected in a dropdown slicer for example: 1-May I'd like to sum the rows 1-May with the next row 2-May for the column Earn and grab the next value 52,106 for the column Earn Cum.. The result should be:
1-May 7,498 52,106
Another example: if the date selected was 30-Apr the result must be:
30-Apr 13,173 50,699
I'm scratching my head trying to do this using a measure in Power BI.
I'll call your table "Data".
Create a measure:
Next Earn =
VAR Current_Date = MAX ( Data[Date] )
VAR Next_Date = Current_Date + 1
RETURN
CALCULATE (
SUM ( Data[Earn] ),
Data[Date] = Current_Date || Data[Date] = Next_Date
)
Create another measure:
Next Cum Earn =
VAR Current_Date = MAX ( Data[Date] )
VAR Next_Date = Current_Date + 1
RETURN
CALCULATE ( SUM ( Data[Earn Cum] ), Data[Date] = Next_Date )
Result:
Note: the code assumes that your dates are sequential (no gaps). If they have gaps, things are a bit more complex.
It will help to have access to date intelligence, so create a date table if you don't have one already. The following dax sets up a small table that just barely covers the sample data in your example.
Date = CALENDAR(Date(2019,4,10),Date(2019,5,5))
Create a relationship between the Dates in your table and the new Date dimension. Add a slicer to your visuals using the Date dimension.
We can use IF and ISFILTERED to check if filtering is being done. If we aren't filtering on Date then we get the normal table behavior. If we are, we'll see our modified result.
Earn _ Alt =
var tomorrow = CALCULATE (
SUM(Table1[Earn]),
dateadd('Table1'[Date], 1, DAY)
)
return Sum(Table1[Earn]) + IF(ISFILTERED`('Date'[Date]),tomorrow,0)`
and
Earn Cum. _ Alt = IF(ISFILTERED('Date'[Date]),
CALCULATE (
SUM(Table1[Earn Cum.]),
dateadd('Table1'[Date], 1, DAY)
),
SUM(Table1[Earn Cum.]))
Results:
-Unfiltered-
-Filtered-

Number of Persons above the Mean

I have this simple data set from Excel:
Date Person Amount
Jan-18 jason 1
Jan-18 fred 2
Jan-18 george 3
Feb-18 jason 10
Feb-18 fred 12
Feb-18 george 15
Feb-18 jim 25
I added two measures:
Amount = SUM( Data[Amount] )
and
Average Amount per Person =
AVERAGEX(
VALUES( Data[Person]),
[Amount]
)
This works as I expect and is dynamic when I select a specific Date:
What I now want is "Number of Persons Above Average" - so in the screenshot only Jim is above 15.50 so the measure should return 1.
My attempt at this measure is this:
Number of Persons Above Average =
CALCULATE(
DISTINCTCOUNT( Data[Person] ),
FILTER(
Data,
SUM( Data[Amount] ) >= [Average Amount per Person]
)
)
As you can see below it just returns the number of persons displayed - in this case 4
How do I amend the above measure to the correct DAX ?
I like to use variables in situations like these:
Number of Persons Above Average =
VAR AveragePerPerson = [Average Amount per Person]
RETURN
CALCULATE ( DISTINCTCOUNT ( Data[Person] ),
Data[Amount] >= AveragePerPerson )
This way you don't have to worry about how the average measure will be computed inside of the CALCULATE and you don't have to use a FILTER function.