I have a Dataset like this
patient_name
age
gender
test_result
Alex
48
M
Positive
Joe
35
M
Negative
Divya
45
F
Positive
And in my power BI Dashboard i need to display a free form table like below
Item Description
Value
Total number of Adult-Male Patients with Positive Test Result
1252
Total number of Adult-Female Patients with Positive Test Result
856
Percent of Positive
2.8
I have the measures created for calculations. I tried to create a custom table with measures, but they are not changing dynamically. The table is showing only static values, when slicer selected value changes.
Is there a better way to present this ?
Thank you,
NSR
first create an empty table
let
Source = Table.FromRows(Json.Document(Binary.Decompress(Binary.FromText("i44FAA==", BinaryEncoding.Base64), Compression.Deflate)), let _t = ((type nullable text) meta [Serialized.Text = true]) in type table [#"Item Description" = _t, Value = _t])
in
Source
then we will fill this table with your measures by creating a table...
Modelling --> New Table
Report Table =
UNION (
Report,
ROW (
"Item Description", "Total number of Adult-Male Patients with Positive Test Result",
"Value",
CALCULATE (
COUNT ( 'Table'[test_result] ),
FILTER (
ALLSELECTED ( 'Table' ),
'Table'[test_result] = "positive"
&& 'Table'[gender ] = "m"
&& 'Table'[age ] > 18
)
)
),
ROW (
"Item Description", "Total number of Female-Male Patients with Positive Test Result",
"Value",
CALCULATE (
COUNT ( 'Table'[test_result] ),
FILTER (
ALLSELECTED ( 'Table' ),
'Table'[test_result] = "positive"
&& 'Table'[gender ] = "f"
&& 'Table'[age ] > 18
)
)
),
ROW (
"Item Description", "Percentage Positive",
"Value",
FORMAT (
DIVIDE (
CALCULATE (
COUNT ( 'Table'[test_result] ),
FILTER (
ALLSELECTED ( 'Table' ),
'Table'[test_result] = "positive"
&& 'Table'[age ] > 18
)
),
CALCULATE ( COUNT ( 'Table'[test_result] ), ALL ( 'Table' ) )
),
"Percent"
)
)
)
did you try ALLSELECTED in your measures?
Total number of Adult-Male Patients with Positive Test Result =
CALCULATE (
COUNT ( 'Table'[test_result] ),
FILTER (
ALLSELECTED ( 'Table' ),
'Table'[test_result] = "positive"
&& 'Table'[gender ] = "m"
&& 'Table'[age ] > 18
)
)
Related
I'm trying to find out how to choose first and last date and quantity for each category, here ORDER_LINE_RELEASE_NO.
ORDER_LINE_RELEASE_NO
WANTED_DATE_OLD
WANTED_DATE_NEW
BUY_QTY_DUE_OLD
BUY_QTY_DUE_NEW
49562_1_9
27.01.2022
1
49562_1_9
27.01.2022
27.01.2022
1
2660
50081_1_1
31.01.2022
6
50081_1_1
31.01.2022
31.03.2022
6
6
50081_1_1
31.03.2022
31.03.2022
6
1210
50084_1_1
10.02.2022
1
50084_1_1
10.02.2022
10.03.2022
1
1
50084_1_1
10.03.2022
10.06.2022
1
1
50084_2_1
10.02.2022
60
50084_2_1
10.02.2022
08.04.2022
60
60
52370_1_1
13.05.2022
3000
52370_1_1
13.05.2022
13.05.2022
3000
2000
In this original table I have the same ORDER_LINE_RELEASE_NO in more rows and I would like to "summarize" it like in the second table here:
ORDER_LINE_RELEASE_NO
FIRST_DATE
LAST_DATE
ORIGINAL_QTY
LAST_WANTED_QTY
49562_1_9
27.01.2022
27.01.2022
1
2660
50081_1_1
31.01.2022
31.03.2022
6
1210
50084_1_1
10.02.2022
10.06.2022
1
1
50084_2_1
10.02.2022
08.04.2022
60
60
52370_1_1
13.05.2022
13.05.2022
3000
2000
So basically in the column FIRST_DATE we have the first value from column WANTED_DATE_NEW (for each category), in LAST_DATE the last value from WANTED_DATE_NEW, in ORIGINAL_QTY is the first value from BUY_QTY_DUE_NEW and in LAST_WANTED_QTY we have the last value from BUY_QTY_DUE_NEW.
I tried to use FIRSTNONBLANK and LASTNONBLANK functions, but they only work fot dates, not for all quantity - for example for 52370_1_1 quantity.
My code in creating new table from another in powerBI was:
PURCH_ORD_LINE_UNIQUE =
ADDCOLUMNS (
DISTINCT ( PURCH_ORD_LINE_ARCH[ORDER_LINE_RELEASE_NO] ),
"FIRST_DATE",
CALCULATE (
FIRSTNONBLANK (
PURCH_ORD_LINE_ARCH[WANTED_DATE_NEW],
PURCH_ORD_LINE_ARCH[WANTED_DATE_NEW]
),
ALLEXCEPT ( PURCH_ORD_LINE_ARCH, PURCH_ORD_LINE_ARCH[ORDER_LINE_RELEASE_NO] )
),
"LAST_DATE",
CALCULATE (
LASTNONBLANK (
PURCH_ORD_LINE_ARCH[WANTED_DATE_NEW],
PURCH_ORD_LINE_ARCH[WANTED_DATE_NEW]
),
ALLEXCEPT ( PURCH_ORD_LINE_ARCH, PURCH_ORD_LINE_ARCH[ORDER_LINE_RELEASE_NO] )
),
"ORIGINAL_QTY",
CALCULATE (
FIRSTNONBLANK (
PURCH_ORD_LINE_ARCH[BUY_QTY_DUE_NEW],
PURCH_ORD_LINE_ARCH[BUY_QTY_DUE_NEW]
)
),
"LAST_WANTED_QTY",
CALCULATE (
LASTNONBLANK (
PURCH_ORD_LINE_ARCH[BUY_QTY_DUE_NEW],
PURCH_ORD_LINE_ARCH[BUY_QTY_DUE_NEW]
)
)
)
Sorry if my question is too stupid, I'm quite new to DAX and PowerBI.
Thanks for any answer.
Tomas
here is my solution : (i will share the sample file at the end, so you can easily understand my approach)
First we will add an index column to the table :
#"Added Index" = Table.AddIndexColumn(#"Changed Type", "Index", 1, 1, Int64.Type)
then, we will add grouped index number column :
Group Ranking =
RANKX (
FILTER (
'Table',
EARLIER ( 'Table'[ORDER_LINE_RELEASE_NO ] ) = 'Table'[ORDER_LINE_RELEASE_NO ]
),
'Table'[Index],
,
ASC,
DENSE
)
finally, we create our table :
Modelling --> New Table
Result Table =
ADDCOLUMNS (
SUMMARIZE ( 'Table', 'Table'[ORDER_LINE_RELEASE_NO ] ),
"FIRST_DATE", CALCULATE ( MIN ( 'Table'[WANTED_DATE_OLD ] ) ),
"LAST_DATE", CALCULATE ( MAX ( 'Table'[WANTED_DATE_new ] ) ),
"ORIGINAL_QTY",
VAR _max =
CALCULATE (
MIN ( 'Table'[Group Ranking] ),
ALLEXCEPT ( 'Table', 'Table'[ORDER_LINE_RELEASE_NO ] ),
NOT ( ISBLANK ( 'Table'[BUY_QTY_DUE_OLD ] ) )
)
RETURN
CALCULATE (
FIRSTNONBLANK ( 'Table'[BUY_QTY_DUE_OLD ], 1 ),
ALLEXCEPT ( 'Table', 'Table'[ORDER_LINE_RELEASE_NO ] ),
'Table'[Group Ranking] = _max
),
"LAST_WANTED_QTY",
VAR _max =
CALCULATE (
MAX ( 'Table'[Group Ranking] ),
ALLEXCEPT ( 'Table', 'Table'[ORDER_LINE_RELEASE_NO ] )
)
RETURN
CALCULATE (
SUM ( 'Table'[BUY_QTY_DUE_NEW] ),
ALLEXCEPT ( 'Table', 'Table'[ORDER_LINE_RELEASE_NO ] ),
'Table'[Group Ranking] = _max
)
)
Here is the sample PBix File for you...
I have a table my_data with the following columns: CATEGORY, SUPPLIER and AMOUNT. I have created measures to calculate the total amount:
Total_Amount := SUM(my_data[AMOUNT])
and to do an ABC classification, I created a ranking:
Ranking:=IF (
ISBLANK ( [Total_Amount] ),
BLANK (),
RANKX (
FILTER (
ALL ( my_data[CATEGORY], my_data[SUPPLIER] ),
my_data[CATEGORY] = MAX ( my_data[CATEGORY] )
),
CALCULATE ( [Total_Amount] )
)
)
a Running Total:
Running_Total:=VAR current_rank = [Ranking]
RETURN
SUMX (
FILTER (
ALL ( my_data[SUPPLIER] ),
[Ranking] <= current_rank
),
[Total_Amount]
)
a Running Total %:
Running_Total(%):=DIVIDE (
[Running_Total],
SUMX ( ALL ( my_data[SUPPLIER] ), [Total_Amount] ),
BLANK ()
)
and the ABC classifier:
ABC_class:=IF (
ISBLANK ( [Total_Amount] ),
BLANK (),
SWITCH (
TRUE (),
[Running_Total(%)] <= [Class_A], "A",
[Running_Total(%)] <= [Class_B], "B",
"C"
)
)
Now, my problem. I have several slicers. Once of them is to choose A, B and/or C from the ABC classification. Note, that in my data there is no column with A, B or C data. The classification is only a measure. So I used a trick to be able to connect the slicer to my Pivot Table and that works fine. PROBLEM: I do not manage to get the right subtotals and grand totals for the following measure:
measure:=VAR Selected_Class =
ALLSELECTED ( ABC_table[Class] )
VAR Supplier_Class =
CALCULATE (
[ABC_class],
ALLEXCEPT (
my_data,
my_data[CATEGORY],
my_data[SUPPLIER],
Period_Table[YEAR]
)
)
RETURN
IF (
HASONEFILTER ( my_data[SUPPLIER] ),
IF (
CONTAINSROW ( Selected_Class, Supplier_Class ),
[Total_Amount],
BLANK ()
),
SUMX (
FILTER (
SUMMARIZECOLUMNS (
StockMvts[SUPPLIER],
"total", [Total_Purchased(EUR)],
"class", [ABC_TotPurchased_byCat&Sup]
),
CONTAINSROW(Selected_Class, [class])
),
[total]
)
)
This last measure doesn't work. It gives an error. The problem is in the SUMX for the subtotals and grand totals. How do I make it to sum only the values of [Total_Amount] for the [SUPPLIER] where the [ABC_class] measure results in one of the values selected in the ABC slicer?
Note, I'm using Power Pivot on Excel.
Thank you!
I would like to calculate in DAX equivalent of Excel function PERCENTRANK.INC but per Category. I admit that I do not know even how to calculate it for Category. Any hints will be highly appreciated.
Here is M code for sample data:
let
Source = Table.FromRows(Json.Document(Binary.Decompress(Binary.FromText("i45WcisqzSwpVtJRSiwoyEkF0oZKsTpIwkmJeUAIZJigipfn56QlpRYVVQLZpqhSyRlQcWOweFhqempJYlJOKlgusagovwTIMMKUK8gvSSzJhzsBRS4/LzM/D0ibo1qFw9HILogFAA==", BinaryEncoding.Base64), Compression.Deflate)), let _t = ((type text) meta [Serialized.Text = true]) in type table [Category = _t, Product = _t, Amount = _t]),
#"Changed Type" = Table.TransformColumnTypes(Source,{{"Amount", Int64.Type}})
in
#"Changed Type"
The measure below would produce the desired result. As there is no PERCENTRANK function in DAX, you can manually calculate it from the results of RANKX and COUNTROWS.
Percent Rank Within Category =
IF (
-- This calculation only makes sense if there is only one product
-- in the current filter context. If there are more than one products
-- or no product in the filters, BLANK should be returned.
HASONEVALUE ( MyTable[product] ),
-- Get all products which belong to the same parent category with
-- the product currently being filtered
VAR tbl = CALCULATETABLE (
-- all products, in the modified filter context of...
VALUES ( MyTable[product] ),
-- no filter on product
REMOVEFILTERS ( MyTable[product] ),
-- and under the same parent category
VALUES ( MyTable[Category] )
)
RETURN
CALCULATE (
-- PERCENTRANK = (<rank of product> - 1)
-- / (<total N of products> - 1)
DIVIDE (
-- Sales rank of each product in ascending order
RANKX (
tbl,
CALCULATE ( SUM ( MyTable[Amount] ) ), ,
ASC
) - 1,
-- Total number of products
COUNTROWS ( tbl ) - 1,
-- When there is only one product, it should return 1
1
)
)
)
Here's how I would write it. Very similar to Kosuke's answer but maybe more readable.
Percent Rank =
VAR ProductsInCategory =
CALCULATETABLE ( VALUES ( MyTable[Product] ), ALLSELECTED ( MyTable[Product] ) )
VAR RankProduct =
RANKX ( ProductsInCategory, [Sales],, ASC )
RETURN
IF (
HASONEVALUE ( MyTable[Product] ),
DIVIDE ( RankProduct - 1, COUNTROWS ( ProductsInCategory ) - 1 )
)
How to calculate rank within Category defined on sales level. Say, that we want to label products with Sales above some threshold with Category "high", and below that threshold with Category "low".
Here is a sample data.
let
Source = Table.FromRows(Json.Document(Binary.Decompress(Binary.FromText("i45WcisqzSwpVtJRSiwoyEkF0oZKsTpIwkmJeUAIZJigipfn56QlpRYVVQLZpqhSyRlQcWOweFhqempJYlJOKlgusagovwS7XEF+SWJJPtwJKHL5eZn5eUDaHNUqHI5GdkEsAA==", BinaryEncoding.Base64), Compression.Deflate)), let _t = ((type text) meta [Serialized.Text = true]) in type table [Category = _t, Product = _t, Amount = _t]),
#"Changed Type" = Table.TransformColumnTypes(Source,{{"Amount", Int64.Type}})
in
#"Changed Type"
My question is a nephew related to its older uncle, who now I want to call in:
Percent Rank within Category =
VAR HasOneValueTrue = HASONEVALUE ( MyTable[Product] )
VAR tbl =
CALCULATETABLE (
VALUES ( MyTable[Product] ),
REMOVEFILTERS ( MyTable[Product] ),
VALUES ( MyTable[Category] )
)
VAR result =
CALCULATE (
DIVIDE (
RANKX (
tbl,
[Sales],
,
ASC
) - 1,
COUNTROWS ( tbl ) - 1
)
)
RETURN
IF (
HasOneValueTrue,
result
)
The difference is that the uncle has Category defined in table column, but now we want to have category calculated on the fly based on sales level. So I tried
replacing the VAR tbl code with the following one with the threshold of 4:
var tbl =
SUMMARIZECOLUMNS (
MyTable[Product],
"CalculatedCategory", IF ( [Sales] > 4, "high", "low" ),
"AggSales", [Sales]
)
Nevertheless, I am not able to refer to such defined variable. I also failed with trial based on creating first a DAX table and then trying to refer to it.
Here are expected results:
References
Here is the family of related questions which members I met on the way while approaching to state this problem.
DAX equivalent of Excel PERCENTRANK.INC per category
DAX RANKX for within Category
DAX REMOVEFILTERS vs ALL
The value parameter in DAX function RANKX
DAX ALLEXCEPT to sum by category of multiple dimension tables
This can be done with a minor modification to my answer here. Copied below:
Percent Rank =
VAR ProductsInCategory =
CALCULATETABLE (
VALUES ( MyTable[Product] ),
ALLSELECTED ( MyTable[Product] )
)
VAR RankProduct = RANKX ( ProductsInCategory, [Sales],, ASC )
RETURN
IF (
HASONEVALUE ( MyTable[Product] ),
DIVIDE ( RankProduct - 1, COUNTROWS ( ProductsInCategory ) - 1 )
)
First, define the calculated category as you suggested.
CalculatedCategory = IF ( [Sales] > 4, "high", "low" )
Then plug that into a filter in the ProductsInCategory variable.
Exp. Results =
VAR CalculatedCategory = [CalculatedCategory] /*Determine current category*/
VAR ProductsInCategory =
CALCULATETABLE (
VALUES ( MyTable[Product] ),
FILTER (
ALLSELECTED ( MyTable[Product] ),
[CalculatedCategory] = CalculatedCategory /*New Condition*/
)
)
VAR RankProduct = RANKX ( ProductsInCategory, [Sales],, ASC )
RETURN
IF (
HASONEVALUE ( MyTable[Product] ),
DIVIDE ( RankProduct - 1, COUNTROWS ( ProductsInCategory ) - 1 )
)
Output:
Edit:
To handle the case where there is only 1 product in a category, you can use MAX to disallow a zero value for the denominator.
Exp. Results =
VAR CalculatedCategory = [CalculatedCategory] /*Determine current category*/
VAR ProductsInCategory =
CALCULATETABLE (
VALUES ( MyTable[Product] ),
FILTER (
ALLSELECTED ( MyTable[Product] ),
[CalculatedCategory] = CalculatedCategory /*New Condition*/
)
)
VAR RankProduct = RANKX ( ProductsInCategory, [Sales],, ASC )
RETURN
IF (
HASONEVALUE ( MyTable[Product] ),
DIVIDE (
RankProduct - 1,
MAX ( COUNTROWS( ProductsInCategory ) - 1, 1 )
)
)
Being very grateful to Alexis Olson, I would like to share a different solution I ended up with. The solution proposed by Alexis works well in my simple example, but it did not work in my complex model. In my complex model the RANKX function does not give the expected results. RANKX returns the same rankings for different sales values.
For the time being this is the solution that works without figuring out what causes RANKX to return ties for different sales values.
First of all, defining Category measure:
CalculatedCategory =
SWITCH (
TRUE (),
NOT ( HASONEVALUE ( MyTable[Product] ) ), "total", -- important to handle totals
[Sales] <= 4, "low",
[Sales] > 4, "high",
"other"
)
It is important to exclude totals from Category. I did it by setting up a different category for totals. Otherwise totals will fall into "high" category bucket. It would distort final results.
I have not used RANKX in calculation of Percent Rank within Category. I used MIXTURE OF COUNTROWS and FILTER.
PercentRank within Category =
VAR category = [CalculatedCategory]
VAR ProductSales = [Sales]
VAR ProductsMatching =
COUNTROWS (
FILTER (
ALLSELECTED ( MyTable[Product] ),
[CalculatedCategory] = category
&& [Sales] >= ProductSales
)
)
var ProductsAll =
COUNTROWS (
FILTER (
ALLSELECTED ( MyTable[Product] ),
[CalculatedCategory] = category
)
)
RETURN
DIVIDE (ProductsMatching-1, MAX( ProductsAll-1, 1 ))
I calculated rows of two tables. First table ProductsMatching has all products that have sales in appropriate category and sales that are higher or equal of the product. ProductsAll returns number of products in category.
I created 80/20 segmentation in my Power BI data model and I got what I wanted (see the table below).
Now I want to calculate new Name column with the next logic: if Cumulative % <=80% show value from the "Customer Name" column, otherwise show "Other" (the result will be the column Name as in the table below).
I tried with this calculated column but it doesn't work (the result isn't correct, it's always "Other"):
80/20 Name = IF([Cumulative Percen.] <= 0.8, SalesReport[Names], "Other")
Note: "Cumulative Percen." is calculated measure.
How can I do this?
In the next step, I'll use a pie chart to show this segmentation where all customers with small cumulative transactions will be categorized as Other.
The calculated measures that I used:
Customer Rank by Transaction =
IF (
HASONEVALUE ( SalesReport[CustName] ),
RANKX (
ALLSELECTED ( SalesReport[CustName] ),
CALCULATE ( [# of Transactions] ),
,
DESC,
DENSE
)
)
Customer Cumulative Transaction =
VAR CurrentCustimerRank = [Customer Rank by Transaction]
RETURN
SUMX (
FILTER (
ALLSELECTED ( SalesReport[CustName] ),
CALCULATE ( [Customer Rank by Transaction] ) <= CurrentCustimerRank
),
CALCULATE ( DISTINCTCOUNT ( SalesReport[CustID] ) )
)
Customer Cumulative Transaction Percen. =
[Customer Cumulative Transaction]
/ CALCULATE (
DISTINCTCOUNT ( SalesReport[CustID] ),
ALLSELECTED ( SalesReport[CustName] )
)