DAX Measure to calculate average with Parameters inside it - powerbi

I have data like this,
App_Num Days Price
A1 10 100
A1 11 150
A2 11 200
A3 12 250
A3 12 300
A4 20 350
A4 21 400
The average of the days is displayed on a card visual as 13.857.
Now, there are two parameters that are set for user to adjust the values and see.
Total Value (Min and Max Range)
Days
For example, if the user selects 0-280- it is expected to list A1 (100 + 150 = 250 less than 280) and A2 (200 being less than 280).
I used a DAX like this and built a table like this,
Apps_in_scope =
Var min_amount = Min('Total Value'[Total Value])
Var max_amount = Max('Total Value'[Total Value])
var required_app_num = SELECTEDVALUE(Table1[App_Num])
Var required_amount = CALCULATE(sum(Table1[Price]),FILTER(Table1,Table1[App_Num] = required_app_num))
var in_scope = if(And(required_amount <= max_amount, required_amount >= min_amount),1,0)
return in_scope
And I was able to produce a Visual like this,
App_Num Apps_in_scope
A1 1
A2 1
A3 0
A4 0
Now after selecting the total price range, if the user selects the days parameter manually to be 15 then my average will shift as per this logic.
A1 has 2 transactions and with in the selected price range of 280 will become (15*2)
A2 has 1 transaction and with in the selected price range of 280 become (15*1)
A3 has 2 transaction and will remain unchanged (12+12)
A4 has 2 transactions and will remain unchanged (20+21)
So my new measure which I want to place on the card is expected to show now (15+15+15+12+12+20+21)/7 = 15.714
How can I write this measure. Kindly help me with this

I'd tweak your measure slightly so that it works better for taking the average:
Apps_in_scope_2 =
VAR min_amount = MIN ( 'Total Value'[Total Value] )
VAR max_amount = MAX ( 'Total Value'[Total Value] )
VAR required_amount =
CALCULATE ( SUM ( Table1[Price] ), ALLEXCEPT ( Table1, Table1[App_Num] ) )
VAR in_scope =
IF ( AND ( required_amount <= max_amount, required_amount >= min_amount ), 1, 0 )
RETURN
in_scope
With this tweak the average is fairly simple:
AvgMeasure =
VAR DaysParam = SELECTEDVALUE ( DaysSlicer[Days] )
RETURN
AVERAGEX( Table1, IF( [Apps_in_scope_2] = 1, DaysParam, Table1[Days] ) )
Edit:
Here's an alternative version that doesn't use the first measure but should scale better to large data tables.
AvgAlternate =
VAR min_amount = MIN ( 'Total Value'[Total Value] )
VAR max_amount = MAX ( 'Total Value'[Total Value] )
VAR DaysParam = SELECTEDVALUE ( DaysSlicer[Days] )
VAR apps =
ADDCOLUMNS (
SUMMARIZE (
Table1,
Table1[App_Num],
"#Price", SUM ( Table1[Price] ),
"#Rows", COUNT ( Table1[Price] )
),
"#Days",
IF (
AND ( [#Price] <= max_amount, [#Price] >= min_amount ),
DaysParam * [#Rows],
CALCULATE ( SUM ( Table1[Days] ) )
)
)
RETURN
DIVIDE ( SUMX ( apps, [#Days] ), SUMX ( apps, [#Rows] ) )

This is assuming that you have separate tables for your Price range and Days selection (as in what-if parameter tables).
My measure =
VAR apps =
SELECTCOLUMNS (
FILTER (
SUMMARIZE ( Table1, Table1[App_Num], "Total Price", SUM ( Table1[Price] ) ),
[Total Price] >= MIN ( 'Total Value'[Total Value] )
&& [Total Price] <= MAX ( 'Total Value'[Total Value] )
),
"App_Num", [App_Num]
)
RETURN
AVERAGEX (
Table1,
IF ( Table1[App_Num] IN apps, SELECTEDVALUE ( Days[Days] ), Table1[Days] )
)

Related

DAX PBI Current month minus Previous month

I have a measure:
_Forecast, % =
VAR ForecastMinimumPercent = 10
VAR ForecastIncreasePercent = 15
VAR sM =
MAX ( T1[PlanDate] ) //Plan Date
VAR fM =
MAX ( '_Date2'[Date] ) //fact Date
VAR sC =
FIRSTNONBLANK ( T1[ProjectCode], 1 ) //Current project code
VAR tP =
//Current forecast cumulative percent
CALCULATE (
SUM ( T1[ForecastPercent] ),
FILTER (
ALLSELECTED ( 'T1' ),
T1[PlanDate] <= fM
&& T1[PlanDate] <= sM
&& T1[ProjectCode] = sC
),
REMOVEFILTERS ( T1[PlanDate] )
)
VAR mM =
// Current Project first Date
CALCULATE (
MIN ( T1[PlanDate] ),
FILTER ( ALLSELECTED ( 'T1' ), T1[ProjectCode] = sC ),
REMOVEFILTERS ( T1[PlanDate] )
)
VAR nD =
ROUNDUP ( DIVIDE ( 100 - tP, ForecastIncreasePercent, 0 ), 0 ) // count of forecast columns
VAR fD =
DATEDIFF ( sM, fM, MONTH ) //dates offsets, '_Date2'[Date] - T1[PlanDate]
VAR P1 = tP + ForecastIncreasePercent * fD //forecasted percent
VAR P2 =
IF ( P1 > 100, 100, P1 ) //does not show values over 100, for example 90+15=105 but show 100
VAR fP =
SWITCH (
TRUE (),
tP < ForecastMinimumPercent, BLANK (),
// if percent <10, then hide
fM < mM, BLANK (),
//hide values if T1[PlanDate] <> '_Date2'[Date]
MAX ( T1[ForecastPercent] ) = 0, BLANK (),
// hide empty percent rows
fM
> DATE ( YEAR ( sM ), MONTH ( sM ) + nD + 1, DAY ( sM ) ), BLANK (),
//does not show 100 more than once
fM <= sM, IF ( HASONEVALUE ( T1[PlanDate] ), BLANK (), tP ),
//if collapsed show first fact values
P2
)
RETURN
fP
This measure give me current forecast percent
But i need get difference current month - previous
How to write right syntax?

a measures for comparing two values and counting the result in Power BI

How can I write a measure to count the number of userID for which sum(x1) is equal to count(order_id), in Power BI?
For example, my data table is:
userID
x1
order_id
141
1
719
172
0
616
172
0
189
172
0
2211
172
0
317
1103
1
98
1103
1
213
1103
1
15
2524
0
4902
2524
1
3620
and I use table visual of power bi for this, to explain my mean:
userID
sum(x1)
count(order_id)
141
1
1
172
0
4
1103
3
3
2524
1
2
Note that the userID column is one of the columns in my data table, and calculating sum(x1) and count(order_id) in this sample is by Power BI default features.
The result for this sample should be 2. I need a measure that returns 2.
Measure1 =
VAR _base1 =
SUMMARIZE ( 'Table 1', 'Table 1'[userID] )
VAR _base2 =
ALLEXCEPT ( 'Table 1', 'Table 1'[userID] )
VAR _ct =
ADDCOLUMNS ( _base1, "X", CALCULATE ( COUNT ( 'Table 1'[order_id] ), _base2 ) )
VAR _sum =
ADDCOLUMNS ( _base1, "X", CALCULATE ( SUM ( 'Table 1'[x1] ), _base2 ) )
VAR _nt =
NATURALINNERJOIN ( _sum, _ct )
RETURN
COUNTROWS ( _nt )
or
Measure4 =
VAR _1 =
COUNTX (
VALUES ( 'Table 1'[userID] ),
VAR _base =
ALLEXCEPT ( 'Table 1', 'Table 1'[userID] )
VAR _1 =
CALCULATE ( SUM ( 'Table 1'[x1] ), _base )
VAR _2 =
CALCULATE ( COUNTROWS ( 'Table 1' ), _base )
VAR _3 =
IF ( _1 = _2, 1 )
RETURN
_3
)
RETURN
_1
This should work
count_valid_rows =
VAR sum_x1_table =
SUMMARIZECOLUMNS ( 'table'[userID], 'table', "sumx1", SUM ( 'table'[x1] ) )
VAR count_orderId_table =
SUMMARIZECOLUMNS (
'table'[userID],
'table',
"countOfOrders", COUNT ( 'table'[x1] )
)
RETURN
COUNTROWS (
FILTER (
NATURALINNERJOIN ( sum_x1_table, count_orderId_table ),
[sumx1] = [countOfOrders]
)
)
Docs of the functions used.
NATURALINNERJOIN
SUMMARIZECOLUMNS
Another suggestion:
Count :=
SUMX (
SUMMARIZECOLUMNS (
'Table'[userID] ,
"Sum" , SUM ( 'Table'[x1] ),
"Count" , COUNT ( 'Table'[order_id] )
),
IF ( [Sum] = [Count] , 1 )
)
As you see from the other answers there are heaps of ways to calculate this. I suggest you look over all the suggestions to understand what is going on in each, and then write out your preferred way of dealing with this type of issue after.
Your new measure may looks like this one:
calculate( countrows('YourTabel'), FILTER(ALL('YourTabel'), somestatementIfneeded && var __x1 = [x1] var __x2 = [x2] return __x1 = __x2))
The main part is to use variable PLACEHOLDER;

How to calculate the average of multiple categories in Power-BI DAX?

I have a table with the following columns:
Industry table
Industry_ID Score
1 2
1 3
2 2
2 4
3 0
4 2
I need to calculate the average of each industry and then the average of those averages.
Like avg of scores of
1=(2+3)/2 =>2.5
2=(2+4)/2 =>3
3=0/1 => 0
4=2/1 => 2
Then average of these averages, i.e (2.5+3+0+2)/4 => 1.85
The tables are in direct query so please consider that. Any help is appreciated. Thank you
For creating the average of distinct values, create a calculated column as:
Average =
var no_ID = 'Table'[Industry_ID]
Return
AVERAGEX(
FILTER(ALL('Table'), 'Table'[Industry_ID] = no_ID),
'Table'[Score]
)
This will give you a column having average of distinct Industry_ID.
For creating an average of averages, create a measure as:
Measure = AVERAGEX(SUMMARIZE('Table', 'Table'[Industry_ID], 'Table'[Average]), 'Table'[Average])
Final Output-
Here are 2 ways to achieve that:
Just switch between Individual and Overall Average variables in the RETURN part, also store this code CALCULATE ( COUNTROWS ( Industry ) ) in a separate measure so that it can be re-used in various places without making the code verbose
Industry Average =
VAR AllIndustryAverages =
AVERAGEX (
ALL ( Industry[IndustryID] ),
DIVIDE ( [Total Score], CALCULATE ( COUNTROWS ( Industry ) ) )
)
VAR IndividualAverages =
AVERAGEX (
VALUES ( Industry[IndustryID] ),
DIVIDE ( [Total Score], CALCULATE ( COUNTROWS ( Industry ) ) )
)
RETURN
IndividualAverages
Industry Average 2 =
VAR VisibleIndustries =
VALUES ( Industry[IndustryID] )
VAR AllIndustryAverages =
ADDCOLUMNS (
ALL ( Industry[IndustryID] ),
"Average",
VAR CurrentIndustryTotalScore = [Total Score]
VAR IndustryCount =
CALCULATE ( COUNTROWS ( Industry ) )
RETURN
DIVIDE ( CurrentIndustryTotalScore, IndustryCount )
)
VAR IndividualAverages =
AVERAGEX (
FILTER ( AllIndustryAverages, Industry[IndustryID] IN VisibleIndustries ),
[Average]
)
VAR OverallAverage =
AVERAGEX ( AllIndustryAverages, [Average] )
RETURN
IndividualAverages

Calculating percentiles by group in Power BI

Below is a sample data and I am looking for a solution to calculate percentiles (25th, 50th, 75th, 100th) for quantity sold grouped by country.
So basically add countries into different buckets from low, mid 1, mid 2 or high depending upon the unit_quantity. So if I create a table shown below in power bi, I want to create a calculated measure that adds the countries into these different buckets.
Currently, what I have tried is create 3 different quartiles in below dax measure and then using IF function i have tried to put them in different buckets :
Quartile =
var FirstQ =
CALCULATE(
PERCENTILE.INC('Sample Table'[unit_quantity], .25),
ALLSELECTED('Sample Table')
)
var SecondQ =
CALCULATE(
PERCENTILE.INC('Sample Table'[unit_quantity], .5),
ALLSELECTED('Sample Table')
)
var ThirdQ =
CALCULATE(
PERCENTILE.INC(Sample Table'[unit_quantity], .75),
ALLSELECTED(Sample Table')
)
var currentVal = SELECTEDVALUE(Sample Table'[unit_quantity])
return
IF(currentVal <= FirstQ, "Low",
IF(currentVal > FirstQ && currentVal <= SecondQ, "Mid",
IF(currentVal > SecondQ && currentVal <= ThirdQ, "Mid 2", "High")
)
)
But the above measure calculates quartiles for the complete table and not grouped by country. Also I want this to be dynamic since I am going to have a slicer for category column so the percentile values should dynamically change according to the category. I am very new to power BI so please bear with me.
You can use PERCENTILEX to run a table calculation, in this case, all countries.
I've added a condition of ISFILTERED to only display the results if the country field is present.
Calculation
Quartile =
VAR SelectedUnit =
SUM ( 'Table'[unit_quantity] )
VAR p25 =
PERCENTILEX.INC (
ALLSELECTED ( 'Table'[country] ),
CALCULATE ( SUM ( 'Table'[unit_quantity] ) ),
0.25
)
VAR p50 =
PERCENTILEX.INC (
ALLSELECTED ( 'Table'[country] ),
CALCULATE ( SUM ( 'Table'[unit_quantity] ) ),
0.5
)
VAR p75 =
PERCENTILEX.INC (
ALLSELECTED ( 'Table'[country] ),
CALCULATE ( SUM ( 'Table'[unit_quantity] ) ),
0.75
)
RETURN
SWITCH (
ISFILTERED('Table'[country]),
SelectedUnit <= p25, "Low",
SelectedUnit > p25
&& SelectedUnit <= p50, "Mid",
"High"
)
Output
country
Unit Sum
Quartile
Bulgaria
2
Low
Canada
83
High
Croatia
49
Mid
India
75
High
Russia
38
Low
United States
69
High

DAX time intelligence functions with nested filters

I have a data structure like this
DateRoll Dataset Date Value Customer
Month Online 1/1/2018 10 Cust1
Month Online 2/1/2018 11 Cust1
Month Online 3/1/2018 12 Cust1
Month Online 4/1/2018 22 Cust1
Quarter Online 1/1/2018 33 Cust1
Quarter Online 4/1/2018 22 Cust1
I have to calculate previous quarter value, I tried different ways but it's not working
1 - Not returning any value.
CALCULATE (
SUM ( 'Data_Rollup_KPI_DNR'[Value] ),
DATEADD ( 'Data_Rollup_KPI_DNR'[Date].[Date], -1, QUARTER ),
FILTER ( Data_Rollup_KPI_DNR, Data_Rollup_KPI_DNR[DateRoll] = "Quarter")
)
2--Nested - Returning overall total
CALCULATE (
CALCULATE (
SUM ( 'Data_Rollup_KPI_DNR'[Value] ),
DATEADD ( 'Data_Rollup_KPI_DNR'[Date].[Date], -1, QUARTER )
),
FILTER ( Data_Rollup_KPI_DNR, Data_Rollup_KPI_DNR[DateRoll] = "Quarter" )
)
3--Nested --Returning overall total
CALCULATE (
CALCULATE (
SUM ( 'Data_Rollup_KPI_DNR'[Value] ),
FILTER ( Data_Rollup_KPI_DNR, Data_Rollup_KPI_DNR[DateRoll] = "Quarter" )
),
DATEADD ( 'Data_Rollup_KPI_DNR'[Date].[Date], -1, MONTH )
)
Tried PREVIOUSQUARTER function too, but its not returning any value.
To take advantage of built in DAX time intelligence functions you will need to to have a contiguous set of dates. I would recommend using a date table. The following code can be used to create a date/calendar table in your model:
Celndar =
Var MinDate = MIN(Data_Rollup_KPI_DNR[Date])
Var MaxDate = MAX(Data_Rollup_KPI_DNR[Date])
Var BaseCalendar = CALENDAR(MinDate, MaxDate)
RETURN
GENERATE (
BaseCalendar,
VAR BaseDate = [Date]
VAR YearDate =
YEAR ( BaseDate )
VAR MonthNumber =
MONTH ( BaseDate )
VAR YrMonth =
100 * YEAR ( BaseDate )
+ MONTH ( BaseDate )
VAR Qtr =
CONCATENATE ( "Q", CEILING ( MONTH ( BaseDate ) / 3, 1 ) )
RETURN
ROW (
"Day", BaseDate,
"Year", YearDate,
"Month Number", MonthNumber,
"Month", FORMAT ( BaseDate, "mmmm" ),
"Year Month", FORMAT ( BaseDate, "mmm yy" ),
"YrMonth", YrMonth,
"Qtr", Qtr
)
)
Once this table exists, mark it as a 'date' table and create a relationship with
Data_Rollup_KPI_DNR[Date]
Then, you can write the following measure to obtain the results you are searching for:
PQSum =
CALCULATE (
SUM ( 'Data_Rollup_KPI_DNR'[Value] ),
PREVIOUSQUARTER ( 'Calendar'[Date] )
)
Hope that helps!
*Edited
You can also create a ranking column to index in a measure:
Rank =
RANKX (
FILTER (
'Data_Rollup_KPI_DNR',
'Data_Rollup_KPI_DNR'[DateRoll] = EARLIER ( 'Data_Rollup_KPI_DNR'[DateRoll] )
),
'Data_Rollup_KPI_DNR'[Date].[Date],
,
ASC
)
Then you can reference a previous quarter using something like the following:
PQSum2 =
CALCULATE (
SUM ( 'Data_Rollup_KPI_DNR'[Value] ),
FILTER (
'Data_Rollup_KPI_DNR',
'Data_Rollup_KPI_DNR'[Rank]
= MAX ( 'Data_Rollup_KPI_DNR'[Rank] ) - 1
),
'Data_Rollup_KPI_DNR'[DateRoll] = "Quarter"
)
but this is hard coded and just plain nasty!
Echoing #steliok that a date dimension is the proper way to handle this; there are plenty of date table templates out there, and a date dimension will work with your data model. If you really really can't add to your data structure for some reason, this should work:
BaseValue = SUM ( 'Data_Rollup_KPI_DNR'[Value] )
PriorQuarter =
VAR CurrentDate = MAX ( 'Data_Rollup_KPI_DNR'[Date] )
VAR CurrentYear = YEAR ( CurrentDate )
VAR CurrentMonth = MONTH ( CurrentDate )
VAR FirstMonthOfCurrentQuarter =
SWITCH (
TRUE (),
CurrentMonth IN {1,2,3}, 1,
CurrentMonth IN {4,5,6}, 4,
CurrentMonth IN {7,8,9}, 7,
CurrentMonth IN {10,11,12}, 10
)
// DATE() does the right thing with negative month args
VAR PriorQuarterDate = DATE ( CurrentYear, FirstMonthOfCurrentQuarter - 3, 1 )
RETURN
CALCULATE (
[BaseValue],
ALL ( 'Data_Rollup_KPI_DNR'[DateRoll], 'Data_Rollup_KPI_DNR'[Date] ),
'Data_Rollup_KPI_DNR'[Date] = PriorQuarterDate,
'Data_Rollup_KPI_DNR'[DateRoll] = "Quarter"
)
This relies on DATE being clever, which it is. DATE ( 2019, -2, 1 ) = DATE ( 2018, 10, 1 ).
Ultimately, my question is why can't you just source the un-rolled up data from the same place that the ETL process is sourcing it?
Date functions are working well when you are using # Day level.
Following link would be helpful to resolve your issue,
https://community.powerbi.com/t5/Desktop/Lead-and-Lag-in-DAX/td-p/649162