Power BI: Profitability 80/20 Analysis (Pareto)
In this post, I will teach you how to build a Pareto analysis dashboard in Power BI. Specifically, the Pareto principle states that 20% of the causes generate 80% of the effects, and vice-versa.
We can apply this empirical principle to different topics, from work (20% of the efforts cause 80% of the results) to relationships (80% of the dates lead to nothing) and business (20% of products generate 80% of the profits).
In our example, we identify the products driving 80% of the profit and compare them to the remaining products.
Below is what we will build.
Our Power BI Pareto Analysis shows us that 42% of products bring in 79% of margin (top products), while 43% of products bring in 11% of margin (bottom products).
The company in the example has thus the opportunity to refocus its efforts, away from the bottom products. The money and time saved on the bottom products can be used to invest in the top products, or invest in new projects or product launches.
Load sales data to Power BI for the Pareto analysis
The source data is a sales table by date and product sold, with information on units, sales value, and margin.
To follow along with the tutorial, you can download the sample sales data from here.
The next step is to create a table with our product classes: top products, middle products, and bottom products.
Create a table for the Pareto classification
Click on Enter Data to create a new table.
The table has a column with the product classes, and a second column to correctly sort the classes.
If you need help with sorting in Power BI, you can check out the article here.
Now we create a second table, with the P&L accounts for the Pareto analysis.
Create a table with the P&L accounts to be analyzed
The table has four rows, one for each account to be analyzed: count of products, units, sales, and margin. This table can have as many lines as you wish to analyze.
Create the Detail by Class visualization
The first visualization of the dashboard is the Detail by Class. To obtain it, we need to add measures for Rank, Cumulated Margin, and Class.
Add a measure for Rank
We add the measure by clicking on New Measure in the Modeling tab.
Here is the measure for Rank:
Rank =
RANKX(ALLSELECTED('Sales table'[Product]),CALCULATE(SUM('Sales table'[Margin])),,DESC,Skip)
We use the function RANKX to obtain the product rank: we rank the Product column of the Sales table in descending order, based on the product margin.
The result is the following: Ford has the biggest margin so it has a rank of 1, Chevrolet has the 2nd biggest margin so it has a rank of 2, and the same logic applies to the remaining products. You can check the screenshot above for an example of the rank.
Add a measure for Cumulated Margin
The cumulated margin is the sum of margin for the current product plus the margin of all products with a lower rank. Below is an example of the cumulated margin.
Ford is the first product (with a rank of 1), thus its cumulated margin is equal to its margin of 3496. Chevrolet is the second product (with a rank of 2), thus its cumulated margin is equal to its margin of 2577 plus the margin of Ford. The cumulated margin for Chevrolet is therefore 6073.
With the same logic, the cumulated margin for Dodge is equal to the margin of Dodge, plus Ford, plus Chevrolet.
The cumulated margin is useful to find the margin generated by the Top N products. In our example, the Top 2 products generate a margin of 6073, the Top 3 products a margin of 8138, and so on.
The DAX formula for the cumulated margin is below.
Cumulated margin =
var currentRank = [Rank]
RETURN SUMX(FILTER(ALLSELECTED('Sales table'[Product]), [Rank]<=currentRank ), CALCULATE(SUM('Sales table'[Margin])))
Now we move on to calculating the class (top, middle, bottom) for each product.
Add a measure for Class
How to calculate a product's Class
To determine which products will be in the top, middle, and bottom classes, we need to decide the percentage of margin going to each class.
In this tutorial, we follow the standard Pareto principle, and we classify the products generating 80% of the margin as Top products.
We then classify the products generating 90% of margin (but not already included in Top products) as Middle products. The remaining products are the Bottom products.
Below is an example with numbers.
The products A through E make no more than 80% of the margin, therefore they have a class of Top products. Afterward, products F and G make no more than 90% of the margin and therefore have a class of Middle Products. Finally, the remaining products H, I, and J are Bottom products.
DAX formula for Class
Below is the DAX formula for Class.
Class =
// 1 – defines percentages
VAR topPercentage = 0.8
VAR middlePercentage = 0.9
VAR totalMargin = CALCULATE(SUM('Sales table'[Margin]), ALLSELECTED())
// 2 – finds the ranks separating top class from middle class, and middle class from bottom class
VAR topRankNumber = MAXX(FILTER(ALLSELECTED('Sales table'[Product]), [Cumulated margin]<= totalMargin* topPercentage), [Rank] )
VAR middleRankNumber = MAXX(FILTER(ALLSELECTED('Sales table'[Product]), [Cumulated margin]<= totalMargin* middlePercentage), [Rank] )
// 3 – returns the class of the selected product
RETURN
IF(
OR(ISBLANK([Rank]), ISBLANK(SUM('Sales'[Margin]))), BLANK(),
IF( [Rank]<=topRankNumber,"Top",IF([Rank]<=middleRankNumber,"Middle","Bottom")))
The first part of the Class formula defines the tresholds: 0.8 (which is equal to 80%) for the Top class and 0.9 (which is equal to 90%) for the Middle class.
The second part of the measure finds the rank separating Top products from Middle products (topRankNumber), and the rank separating Middle products from Bottom products (middleRankNumber). With the numbers of the above example, the topRankNumber is 5 (products with rank lower than 5 are Top product). Similarly, the middleRankNumber is 7 (products with rank lower than 7 and higher than 5 are Middle product).
The last part of the formula returns the product class, based on its ranking.
All the measures are now ready to create the Detail by Class visualization in Power BI.
We can move on to the P&L by class visualization.
Create the P&L by class visualization.
This visualization shows the Product Count, Sales, and Margin by class.
We have 22 products categorized as top products, 8 as middle products and 23 as bottom products.
While the top products generate a margin of almost 30 000, the middle and bottom products both generate around 4 000 in margin.
A new DAX measure ‘Value by Class’ can return all of the information needed for these charts. Below is the formula for it.
Value by Class =
VAR currentClassTable = FILTER(ALLSELECTED('Sales table'[Product]), [Class]= SELECTEDVALUE('Pareto classification'[Product class]))
RETURN SWITCH (SELECTEDVALUE('P&L'[P&L]),
"Count", COUNTROWS(currentClassTable)
, "Units" , SUMX(currentClassTable, CALCULATE(SUM('Sales table'[Units])))
, "Sales" , SUMX(currentClassTable, CALCULATE(SUM('Sales table'[Sales])))
, "Margin", SUMX(currentClassTable, CALCULATE(SUM('Sales table'[Margin]))))
There are two parts to the formula.
The first part of the formula creates a table called ‘currentClassTable’ with the products of the selected class (top, medium or bottom).
The second part of the formula calculates product count, units, sales and margin for the selected P&L line.
Once your measure is ready, we move on to configure the bar chart.
It should be configured as follows: Product class as Axis, and 'Value by Class' as Value.
Finally, we filter the three Bar Charts for the three P&L lines: count, sales and margin.
We can now move to the last and most exciting chart, the Pareto Analysis chart!
Create the Power BI Pareto Analysis visualization.
We need one last measure, which is the percentage by class. The logic is similar to the Value by Class, however in percentage instead of value. The formula is below.
% by Class =
VAR currentClassTable = FILTER(ALLSELECTED('Sales table'[Product]), [Class]= SELECTEDVALUE('Pareto classification'[Product class]))
RETURN SWITCH (SELECTEDVALUE('P&L'[P&L]),
"Count", COUNTROWS(currentClassTable)/DISTINCTCOUNT('Sales table'[Product])
, "Units" , SUMX(currentClassTable, CALCULATE(SUM('Sales table'[Units])))/SUM('Sales table'[Units])
, "Sales" , SUMX(currentClassTable, CALCULATE(SUM('Sales table'[Sales])))/SUM('Sales table'[Sales])
, "Margin", SUMX(currentClassTable, CALCULATE(SUM('Sales table'[Margin])))/SUM('Sales table'[Margin]))
The difference compared to the previous formula is that now we divide by the total values, to obtain the percentage by class.
The chart type is ‘Ribbon chart’; we configure it by choosing P&L for Axis and Product Class for Legend.
And we have our Pareto Analysis chart!
I sincerely hope that this tutorial was helpful for you.
13 Comments
Thanx a lot for your job!
I'm happy you find this useful
But! PowerBi automatically created a link between tables P&L and Pareto Classification. And i'm killed the halfday to understand why the model does not work!
I'm sorry to hear that you spent half a day to figure it out. Power BI did not link the tables when I built this model, so I did not precise this part in the tutorial. I'll modify the explanation now to make this does not happen to anyone else.
For any future issue on the tutorial you find here, send me an email right away to lc@finance-bi.com. I'll look into it, so you don't spend half a day to troubleshoot it
LC
Thank you for the entire walk through in detail, really appreciated.
It works, but really slow. Is there other way around to make it faster, maybe by changing the way of how the measures are being structured?
Hi Kal,
thank you for your message.
If the formulas are too slow with your data model, I would look at recreating the formulas in Power Query.
Power BI optimizes tables before loading them from Power Query. Therefore, all new columns added in Power Query will be optimized when loaded to Power BI.
There is however an additional aspect to consider when doing this: the columns added in Power Query are not 'dynamic' like DAX measures.
Power Query calculations do not update based on selections and filters applied by users.
Does that above make sense and does it help you?
If you wish, I would be happy to discuss more your specific data model. For that, you can send me an e-mail to lc@finance-bi.com
Regards
Luca
Hi, this is super helpful! Similar to what the earlier commenter said, I'm experiencing slowness, but I think that's just the cost of having the dynamic calculation vs. static in Power Query.
I was actually wondering if you had thought of a way to filter the product list based on "Top", "Middle", and "Bottom". We have thousands of articles we are trying to measure, so the graphs are amazing, but it would help if we could drill down to see what articles (Products) made up the Top bucket. However, when I try this, because of the dynamic calculation, it continues to recalculate top/middle/bottom.
Anyway, I hope that makes sense. I am playing around with how to keep filters on the measures even when I drill lower, but haven't figured it out yet.
Hi Dan,
thank you for leaving a message!
Regarding finding out which articles make the Top Bucket, what about the table on the left of the dashboard? The table has a Class column which you can use to see only the Top products.
And you could also extract that table to Excel.
Regarding the slowness, I understand your comment. Moving the calculations to Power Query would definitely help for the performance, but as you say the calculation would no longer be dynamic.
If you already know the type of filtering that your users might do (for example: filter the categories A, B, C) then you could run the calculations 4 times in Power Query: one time for total, and one time each for category A, B, C.
This could give you the best of both worlds: better performance, and the ability to filter.
The negative aspect, however, is that this only works if you have a handful of filter options. Too many filter options and your table would become massive with all the calculations.
I hope this helps you!
Luca
I like this article and learn your way.
Thanks,
I do not find the link to download the PB file.
Will you please send it to me?
thanks
john
Hi John,
thanks for posting!
At the bottom of each post, there is form to enter your email and subscribe to Finance BI.
Once you enter your email and subscribe, you will receive the link to downloaded the PB file.
Does this help you?
Luca
Luca, this is great, thank you very much. A great guide for how to leverage the ribbon visual. One question for you. Along the bottom of the ribbon visual, my metrics are not showing up in the correct order from left to right. I tried the "Order by" column, but did not see that it made a difference.
Am I missing something?
Hi Paul,
I agree, I think the ribbon is a great way to visualize the Pareto analysis.
Regarding the ordering of metrics, you need to do a custom sort based on the column 'P&L Order'.
You can take a look at the following article for help with it: https://finance-bi.com/blog/power-bi-custom-sort-a-column/
And you can of course create the Order column with any number you wish, so you can sort it exactly how you want.
Best of luck with your analysis,
Luca
Yep, forgot to force the sort by the "Order"column. Thanks again.