Calculating percentiles by group in Power BI - powerbi

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

Related

calculate the difference between first and last value of each Id and count those with 10% decrease in DAX Power BI

have a simple table like this
ID value date
A 100 2020-01-01
B 80 2019-01-01
A 90 2022-01-01
A 130 2021-01-01
B 100 2021-01-01
and want to know how many IDs had 10% increase within a selected time period, IDs might not necessarily have an entry on Min(Date) or Max(Date), I'd like to know the difference between first and last value within the selected time period
I came up with something like this but not sure if it's working :
Measure=
Var FirstValue=
SUMX (
VALUES( table [ID] ),
CALCULATE ( MIN ( table[value]), FIRSTDATE ( 'Date'[DATE] ) )
)
Var LastValue =
SUMX (
VALUES( table[ID] ),
CALCULATE ( MIN ( table[value] ), LASTDATE ( 'Date'[DATE]) )
)
Return sumx(table,if( (FirstValue -LastValue )/FirstValue> 0.1 , 1,0)
)

Ignore one of the filters PowerBI sends to SSAS

I need to calculate pareto but in graph we can only see top 10 items but pareto should be calculated from all items in the selected date period. So e.g. if I have date 1.10.2021 and I have 20 values for that date. I can display only 10 in powerbi, how can I ignore filter for TOPN10 in dax and calculate pareto from 20 values (in graph it wont show 100 percent for pareto calculation)
I am posting filters from PowerBI
DEFINE
VAR __DS0FilterTable =
TREATAS({FALSE,
BLANK()}, 'Breakdown'[Less then 30 sec])
VAR __DS0FilterTable2 =
TREATAS({TRUE}, 'Breakdown'[IsReportedInterval])
VAR __DS0FilterTable3 =
TREATAS({"Reported"}, 'Reported Filter'[Reported])
VAR __DS0FilterTable4 =
TREATAS({DATE(2021, 10, 1)}, 'Date'[Date])
VAR __DS0FilterTable5 =
TREATAS({"Morning"}, 'Shift'[Shift Name])
VAR __SQDS0BodyLimited =
TOPN(10, __SQDS0Core, [Breakdown__min_], 0)
Here is Pareto calculation - If I use ALLSELECTED pareto is calculated from rows filtered by powerbi filters, when I use ALL it will remove all filters which is not correct because I would get sum of all rows excluding date filter. Any ideas ?
Pareto Breakdown Description:=
VAR TotalQuantity =
CALCULATE ( SUM ( Breakdown[DurationSeconds] ), ALLSELECTED( Breakdown ) )
VAR AllBreakdowns =
SUM ( Breakdown[DurationSeconds] )
VAR SummarizedTable =
SUMMARIZE (
ALLSELECTED ( Breakdown ),
'Breakdown'[Description SK],
"Amount", SUM ( Breakdown[DurationSeconds] )
)
VAR CumulativeSum =
SUMX ( FILTER ( SummarizedTable, [Amount] >= AllBreakdowns ), [Amount] )
RETURN
DIVIDE( CumulativeSum, TotalQuantity )
It will sound maybe little bit silly but I found a workaround - so I removed the filter to show only top 10 rows and within the graph I changed minimum category width which at the end shows only 10 bars (10 are hidden)

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

Project revenue calculation in DAX

I need to calculate the ongoing revenue for installation + maintenance for projects and calculate the monthly revenue for controlling purposes in DAX in Power BI.
The problem is the following.
The projects are stored in a table CONTRACTS like this:
And I have a separate date table INST_DATE_TABLE:
The tables are connected via the [INSTALLATION_DATE] field.
For every month the revenue is the total of the [INSTALLATION_REVENUE] if the installation was carried out that month plus from the first month on the monthly maintenance revenue which is given as the [MAINTENANCE_COST_PER_UNIT] * [MAINTENANCE_UNIT] / 12.
And the maintenance revenue should be only calculated if the current date is beyond the installation date!
Some contracts are not yet signed, so they dont't have an installation date set (NULL)
So the INSTALLATION REVENUE DAX is like this:
.INSTALLATION_REVENUE =
CALCULATE (
SUMX(CONTRACTS;
CONTRACTS[INSTALLATION_REVENUE]
);
CONTRACTS[INSTALLATION_DATE] > 0
)
And the MONTHLY REGULAR REVENUE is like this:
.REGULAR_REVENUE =
CALCULATE (
SUMX(CONTRACTS;
CONTRACTS[MAINTENANCE_COST_PER_UNIT]*CONTRACTS[MAINTENANCE_UNIT]
) / 12;
CONTRACTS[INSTALLATION_DATE] > 0
)
For all dates I can calculate the cash flow of the latter like this:
.REGULAR_REVENUE_ONGOING =
CALCULATE (
[.REGULAR_REVENUE];
ALL(INST_DATE_TABLE[INSTALLATION_DATE])
)
which gives me a nice series of monthly revenues for all periods. But I only would like to see this for the periods that are beyond the installation date!
So lets say filtered on contract 1 I have now the following cash flow:
But for periods before 2019.04.01 I would like to see zeros!
How can I do that?
I just can't filter on dates referring to the installation date of the project!
After I have the expected result for one contract it would be easy to sum it up for all contracts like this
.TOTAL_REVENUE =
[.INSTALLATION_REVENUE] + [.REGULAR_REVENUE_EXPECTED]
UPDATE:
I created a cumulative total to display the ongoing revenue as such:
.REGULAR_REVENUE_ONGOING =
CALCULATE (
[.REGULAR_REVENUE];
FILTER(
ALL(INST_DATE_TABLE[INSTALLATION_DATE]);
INST_DATE_TABLE[INSTALLATION_DATE
<=MAX(INST_DATE_TABLE[INSTALLATION_DATE])
)
)
this displays the correct series, but now I have another problem. When I try to cumulate this already cumulative data series it does not add up as a cumulative data series!
Any help would be appreciated
.REVENUE_TOTAL_CUMULATIVE =
CALCULATE(
[.REVENUE_TOTAL];
FILTER(
INST_DATE_TABLE;
INST_DATE_TABLE[INSTALLATION_DATE] <= MAX(INST_DATE_TABLE[INSTALLATION_DATE])
)
)
Assuming there are no end dates to your ongoing revenue, then try:
.REGULAR_REVENUE_ONGOING =
VAR DateMin =
CALCULATE(
MIN ( CONTRACTS[INSTALLATION_DATE] ),
ALL ( INST_DATE_TABLE )
)
VAR DateMax =
MAX ( INST_DATE_TABLE[INSTALLATION_DATE] )
RETURN
SUMX (
FILTER (
ALL ( INST_DATE_TABLE ),
INST_DATE_TABLE[INSTALLATION_DATE] >= DateMin && INST_DATE_TABLE[INSTALLATION_DATE] <= DateMax
),
[.REGULAR_REVENUE]
)
And for a cumulative total revenue:
.REVENUE_TOTAL_CUMULATIVE =
VAR DateCurrent = MAX ( INST_DATE_TABLE[INSTALLATION_DATE] )
VAR CumulativeInstallationRevenue =
CALCULATE (
[.INSTALLATION_REVENUE],
FILTER (
ALL ( INST_DATE_TABLE ),
INST_DATE_TABLE[INSTALLATION_DATE] <= DateCurrent
)
)
VAR CumulativeOngoingRevenue =
SUMX (
FILTER (
ALL ( INST_DATE_TABLE ),
INST_DATE_TABLE[INSTALLATION_DATE] <= DateCurrent
),
[.REGULAR_REVENUE_ONGOING]
)
RETURN
CumulativeInstallationRevenue + CumulativeOngoingRevenue
See https://pwrbi.com/so_55808659/ for worked example PBIX file

DAX custom Grand Total not behaving as expected

I have a Measure which calculates a cumulative total:
CumulativeCount:=
VAR date1 = MAX( DimDate[Date] )
VAR date2 = MAX( FactTable[EndDate] )
RETURN
CALCULATE (
SUM( FactTable[Count] ),
DimDate[Date] <= date1,
DimDate[Date] <= date2,
ALL( DimDate[Date] )
)
And another, actually used in the Pivot Table, which, when it's calculating the Grand Total, is supposed to add up the cumulative totals for each date:
CumulativeCountForPivot:=
IF (
-- If calculating for one group
COUNTROWS( VALUES( FactTable[Group] ) ) = 1,
-- Do core logic
[CumulativeCount],
-- Else add up the results from each group
SUMX(
VALUES( FactTable[Group] ),
[CumulativeCount]
)
)
I don't understand why the Grand Total in the final column is 12, not 6.
The reason is that the grand total is for GroupA and GroupB combined and there is a cumulative count of 12 on that date (6 for each group).
On 06/01/2017 there are no records for GroupA so the [CumulativeCount] measure is returning a blank, even though there are records before that date and the count would be 6. If you added a record for GroupA with a Count of 0 on 06/01/2017, then you would see 6 appear.
If you want a measure that only shows 6 on that date, then try something like this:
CountForPivot =
VAR TempTable = SUMMARIZE(FactTable,
FactTable[Group],
FactTable[EndDate],
"Cumulative",
CALCULATE(SUM(FactTable[Count]),
FILTER(ALLEXCEPT(FactTable, FactTable[Group]),
FactTable[EndDate] <= MAX(FactTable[EndDate])
)
)
)
RETURN SUMX(TempTable, [Cumulative])