Applying top and bottom N in one Power BI visualization - powerbi

Charts and visuals on Power BI can be filtered to the top n records for easier at-a-glance reporting. However, if I want to report the top and bottom records (eg: top 10 and bottom 10 dollar amounts) I need to place two visuals. This consumes more report space and breaks the cohesion of the page.
Is there a way to select two data subsets in one graph for this kind of reporting?

Here is the sample data I threw together.
On top of that, I created a simple measure for the Total Amount.
Total Amount = SUM(Data[Amount])
With that I created a new measure that will essentially flag each row as being in the Top or Bottom 3 (you can change the number to meet your needs).
This measure first checks if there is a value for Total Amount and "removes" any that have a blank value ("removes" by making the flag blank and thus will never be included in any filtering or such).
TopBottom =
IF(
ISBLANK([Total Amount]),
BLANK(),
IF(
RANKX(ALL(Data), [Total Amount], , ASC) <= 3 || RANKX(ALL(Data), [Total Amount], , DESC) <= 3,
1,
0
)
)
Once you have the ranking flag measure, you can add it to your visual and then filter to where the measure is 1.
Once that is all finished, you should have a visual only showing the entries you care about. Here is the full list of data with the flag visible and the resulting table when applying the filter.

Consider this as a slight improvement to the accepted answer. With this one, you don't need to change the formula whenever you want to change how many you want to see.
The only control you will need to change is the filter.
RankTopBottom = RANKX(ALL(Data), [Total Amount], , ASC) *
RANKX(ALL(Data), [Total Amount], , DESC)
It uses basically the same principle of the accepted answer, but instead of using an IF, we multiply both rankings. The smallest values will be the edges, the gratest values will be the middle.
So, when filtering, use "bottom" N, and pick an even number. (Or add a negative sign if you want the "top" N instead)
A quick result of multiplying inverse ranks:

Related

Why I get different Total, but same values?

I needed to replace this measure:
CALCULATE([GM % YTD], SAMEPERIODLASTYEAR('Date'[Date]))
By this one:
VAR VAR1 = ADDCOLUMNS( VALUES(Revenue[Key_Client]),
"Col1", CALCULATE([GM % YTD], SAMEPERIODLASTYEAR('Date'[Date]),
REMOVEFILTERS(Revenue[Type],Revenue[SectorType]))
)
RETURN AVERAGEX(VAR1, [Col1])
Both measures point to GM % YTD, which is:
CALCULATE([GM %], DATESYTD('Date'[Date],"31/05"))
I get this, when I display them side by side:
The values are ok, my problem is with the Total. I am unable to find how/where is the aggregation on the left column done... How is that 73,2% achieved? It doesn't seem to be average...
Also… how can I force the measure on the right to do the same aggregation?
In the ADDCOLUMNS version, you are iterating over each Revenue[Key_Client] and only averaging after the [GM % YTD] has been calculated for each one separately. For a single client, there's only one thing to average, so the value isn't affected by that step.
Generally, you want to compute the measure over all clients together rather than averaging the individual numbers together to get a standard weighted average rather than an average where all clients are weighted equally.

PowerBI - Dynamic TopN + Others depending on slicer

I have data structured like this
Date, Group, Value
1/1/2020, A, 10
2/1/2020, A, 5
3/1/2020, A, 7
1/1/2020, B, 1
2/1/2020, B, 3
3/1/2020, B, 7
1/1/2020, C, 1
2/1/2020, C, 3
3/1/2020, C, 7
With ~20 Groups.
I want to create Pie/Tree chart, to show f.e. Top 5 Values and the rest as OTHER.
It's pretty simple to do once, but what if I have slicer that filters the graph by Years or Months, accuired from Dates Table connected to Date column?
So when I check only 2020, it would show Top N + Others for 2020 only, and not all data?
Only TopN in graph filters isn't enough, since it sums values on graph to 100%, and I want to see what's the real percentage in terms of all Groups.
Tangent: I wrote a lengthy reply telling you how to make a proper measure that would return the correct percentage, and in the end realized TopN would make it sum up to 100% anyway. So, always keep that in mind: if you pay attention, you'll learn even when you teach ;) Anyway,
What I would try then, is to have a specific measure, such as
[Value % (top N)] =
var denominator = CALCULATE ( [Value], ALLSELECTED ( Data_table ))
var rank = RANKX ( VALUES ( Data_Table[Group] ), [Value] ))
return IF ( rank <= *N*, DIVIDE ( [Value], denominator ))
and then, remove the TOPN filter from the visual. For groups which are not in the top N, the measure will return blank, so they won't show on a visual.
If, however, you want to show the "Others" line, with the rest of the sum, then you need to work a little more. For one thing, you need to have a line with "Others" for the group, on the same table as the actual groups you're summing, and the measure will need more branching logic to take that into account.
But the basic logic is still the same, using RANKX over the values in the Group column, then returning blank for most items (IF() by default returns a blank if the condition is false, but you can always have the measure return BLANK() yourself, in some edge cases).

Power BI (DAX) Multiple Filter Sum Total

I am a new user of Power BI. I have a two step process which I need help with.
(1) - Calculate filtered (string) sum totals, which update based on slicers in report
(2) - Calculate ratio using outputs from Step 1 by quarter.
Data set approximates this:
The idea is that my report should be able to calculate Price per Liter if filtered by Color and if filtered by Shade (ie. multiple filters, but not restricted), by Quarter, so the trend can be plotted.
So far, I can calculate what I need using only one filter.
Total Price per quarter =
CALCULATE (
SUM ( Data[Price] ),
FILTER ( data, data[Quarter] = EARLIER ( data[quarter] ) ),
FILTER ( data, data[Colour] = EARLIER ( data[Colour] ) )
)
The trouble is that this approach doesn't seem to be so accurate when including more than one filter. From what I can gather it seems to double count Price (if say using two filters)
Total Price (TP) should essentially adjust for each filter (Quarter, Colour & Shade). If Q1 Selected TP = 2800 (1000+500+600+700); If Q1 & Green, TP = 1500 (1000+500); If Q1, Green & Light, TP = 1000. I know it is a simple problem, but I am not quite familiar with the functions and syntax just yet.
Can you please provide me with a DAX expression which might achieve this?
Just use the following measure without any filter (right click on your table and add measure):
Total Price = SUM(data[Price])
Now put that measure into a KPI visual and put the rest of your columns as slicers on the report. You will see if you select for example Q1 the KPI visuals value will change. The same goes for every filter combination you will choose.

Grand averaging a measure where there is missing data in PowerBI and DAX

I am trying to get my head around DAX and am struggling. I have a PowerBI Matrix in which I need to calculate the average of a measure. The measure is '% of population' and on the surface it appears to work exactly as expected.
It calculates correctly in the top matrix for the two levels and also summarises correctly in the bottom table.
As an example, I have highlighted in red the order of calculations for "A3"
For the record the % population is set to
% of Population = sum(Data[Value])/sum('Level'[Population])
The problem occurs when I filter on the Country and only select Country 2...
Country 2 does not have data for "D13". Although the Values sum up correctly (170), the Sum of the Population includes the 300 from the missing D13 row making a total of 600 and the '% population' of 28.33% (instead of 170 / 300 = 57%)
I am happy to turn off the group totals in the top grid so that the 28.33 does not show; so my real problem is actually with the bottom grid.
I think I need a new measure to be displayed in the bottom grid. I think it simply needs to sum up the values and divide by the sum of the populations - but only when the value is present. How do I do that?
Or am I totally on the wrong track and there is an obvious answer that I am missing?
The PowerBI file can be downloaded from here
Thanks in advance.
The reason this is happening is that the Country table does not filter the Level table in the relationship diagram since they both only filter one way to the Data table and there are no other relationships.
Without changing your data model, one way to fix this in DAX is to specify that you only want to count Population where Level[LevelId] matches a Data[SecondLevelId] in your current filter context.
Population =
DIVIDE (
SUM ( Data[Value] ),
CALCULATE (
SUM ( 'Level'[Population] ),
'Level'[LevelId] IN VALUES ( Data[SecondLevelId] )
)
)

How to change value in column based on the other table that is not related

I have a table with column num that contain numbers from 10,000 to 1,000,000. This table need to be used as slicer.
Second Table contains ClaimNumber and LossAmount per each claim.
How can I generate a new dynamic column (or measure) that would decrease LossAmount per ClaimNumber based on number chosen in a slicer. Only, of course, if Loss Amount is greater than the num column.
For example if I chose 40,000 then all Claims that have LossAmount more than 40,000 need to be equal 40,000.
On a picture below you see, that choosing 40,000 cap Claim5 and Claim7 became 40,000.
Is it possible to achieve this?
You definitely need to do this as a measure since a calculated column cannot be responsive to slicers.
The measure should be fairly simple.
Capped Loss Amount =
VAR MaxLoss = MAX(Slicer[num])
RETURN
SUMX(
Claims,
IF(
Claims[LossAmount] > MaxLoss,
MaxLoss,
Claims[LossAmount]
)
)