Power BI What if analysis - powerbi

I have a matrix Power BI visualization which is like
Jan Feb Mar April
Client1 10 20 30 10
Client2 15 25 65 80
Client3 66 22 54 12
I have created 3 what if parameters slicer table (having values from 1 to 4) for each client
For example, If the value of the first slicer is 1 and the second is 2 and the third is 2 then I want
Jan Feb Mar April
Client1 0 20 30 10
Client2 0 0 65 80
Client3 0 0 54 12
That is, it should replace the value with zero. I have been able to achieve that for one client using Dateadd function (by adding month)
Measure = CALCULATE(SUM('Table'[Value]),
DATEADD('Table'[Column], Parameter[Parameter Value], MONTH))
and I have used this measure to display the value, but how to make it work for the other two clients as well .

Let say you have three parameter tables as follows
Parameter1 Parameter2 Parameter3
Value1 Value2 Value3
------ ------ ------
1 1 1
2 2 2
3 3 3
4 4 4
and each of them has its own slicer. Then the measure you are after might look something like this:
Measure =
VAR Val1 = MAX(Parameter1[Value1])
VAR Val2 = MAX(Parameter2[Value2])
VAR Val3 = MAX(Parameter3[Value3])
VAR CurrClient = MAX('Table'[Client])
VAR CurrMonth = MONTH(DATEVALUE(MAX('Table'[Month]) & " 1, 2000"))
RETURN SWITCH(CurrClient,
"Client1", IF(CurrMonth <= Val1, 0, SUM('Table'[Value])),
"Client2", IF(CurrMonth <= Val2, 0, SUM('Table'[Value])),
"Client3", IF(CurrMonth <= Val3, 0, SUM('Table'[Value])),
SUM('Table'[Value])
)
Basically, you read in each parameter and compare them to the month in the current cell.

Related

How to create chain index USING dax?

I have a table with department, category, year and sales. See the sample table below:
Table name: ABC
department
category
year
sales
Finance
1
2012
20
HR
1
2012
30
Marketing
1
2012
60
Finance
2
2012
50
HR
2
2012
15
Marketing
2
2012
17
Finance
1
2013
60
HR
1
2013
40
Marketing
1
2013
90
Finance
2
2013
7
HR
2
2013
20
Marketing
2
2013
22
Finance
1
2014
50
HR
1
2014
39
Marketing
1
2014
120
Using the DAX query language, I was able to create the relative index
department
category
year
sales
relative_index
Finance
1
2012
20
100
HR
1
2012
30
100
Marketing
1
2012
60
100
Finance
2
2012
50
100
HR
2
2012
15
100
Marketing
2
2012
17
100
Finance
1
2013
60
(60/20)*100 = 300
HR
1
2013
40
(40/30)*100 = 133
Marketing
1
2013
90
(90/60)*100 = 150
Finance
2
2013
7
(7/50)*100 = 14
HR
2
2013
20
(20/15)*100 = 133
Marketing
2
2013
22
(22/17)*100 = 129
Finance
1
2014
50
(50/60)*100 = 83
HR
1
2014
39
(39/40)*100 = 97.5
Marketing
1
2014
120
(120/90)*100 = 133
I used the following dax code to create the relatie_index
Relative_Link =
//Inception = get the minimum year
var Inception = MIN(ABC[year])
//FY_LY = get the previous year
var FY_LY = ABC[year]-1
//LY_level = get the previous year's sales for a department and category
previous year
var LY_level = calculate(sum(ABC[sales]), filter(allexcept(ABC, ABC[department],
ABC[category]), ABC[year]=FY_LY))
return if(ABC[year]=Inception, 100, (ABC[sales]/LY_level)*100)
I am having trouble creating the chain_index column
department
category
year
sales
relative_index
chain_index
Finance
1
2012
20
100
100
HR
1
2012
30
100
100
Marketing
1
2012
60
100
100
Finance
2
2012
50
100
100
HR
2
2012
15
100
100
Marketing
2
2012
17
100
100
Finance
1
2013
60
(60/20)*100 = 300
(100*300)/100 = 300
HR
1
2013
40
(40/30)*100 = 133
(100*133)/100 = 133
Marketing
1
2013
90
(90/60)*100 = 150
(100*150)/100 = 150
Finance
2
2013
7
(7/50)*100 = 14
(100*14)/100 = 14
HR
2
2013
20
(20/15)*100 = 133
(100*133)/100 = 133
Marketing
2
2013
22
(22/17)*100 = 129
(100*129)/100 = 129
Finance
1
2014
50
(50/60)*100 = 83
(83*300)/100 = 249
HR
1
2014
39
(39/40)*100 = 97.5
(97.5*133)/100 = 130
Marketing
1
2014
120
(120/90)*100 = 133
(133*150)/100 = 199.5
I am trying to use the following formula:
Chain_Index =
//Inception = get the min year
var Inception = MIN(ABC[year])
//FY_LY = get the previous year
var FY_LY = ABC[year]-1
//Next_Year = Inception + 1
var next_year = Inception + 1
//LY_ChainIndex_Value = get the previous chain index value from previous year
var LY_ChainIndex_Value = calculate(sum(ABC[chain_index]), filter(allexcept(ABC,
ABC[department], ABC[category]), ABC[FY_CY]=FY_LY))
return if(ABC[FY_CY]=Inception, 100, (ABC[relative_index]*LY_ChainIndex_Value)/100)
I am getting the following error message:
A circular dependency was detected: ABC[chain_index].
I am trying to create chain index value described in this youtube video:
https://www.youtube.com/watch?v=TXzNvxCB0_g&t=234
Thanks for reading and help will be appreciated
After some quick testing, the following column works great to calculate the chain_index:
chain_index =
VAR _ly = [year] - 1
VAR _ly_index =
CALCULATE (
SUM ( 'ABC'[relative_index] ) ,
ALLEXCEPT ( 'ABC' , 'ABC'[department] , 'ABC'[category] ) ,
'ABC'[year] = _ly
)
RETURN
IF (
ISBLANK ( _ly_index ) ,
100 ,
( [relative_index] * _ly_index ) / 100
)
Basing the relative_index on the following:
relative_index =
VAR _ly = [year] - 1
VAR _ly_sales =
CALCULATE (
SUM ( 'ABC'[sales] ) ,
ALLEXCEPT ( 'ABC' , 'ABC'[department] , 'ABC'[category] ) ,
'ABC'[year] = _ly
)
RETURN
IF (
ISBLANK ( _ly_sales ) ,
100 ,
100.0 * ( [sales] / _ly_sales )
)
I suspect the circular dependency is caused by whatever it is you are doing to calculate this column 'ABC'[FY_CY] - a column you do not need for this calculation at least.
Unless you are planning to deploy these indexing columns for categorization or slicing, then the best practice is to calculate these values using measures instead of making your data model bigger with calculated columns.

DAX - Rankx by multiple Categories Issue

I have 4 Categories (GP, ID, Age, Date). I would would like to create calculated column and group by GP, ID, and Age and Rank/ count by Date to see how many months each member has in past 24 month.
My Code works until I have members who cancelled their membership for a few months and then resumed after. I need to restart from the first month after skip. for example :
GP ID AGE DATE RKING Desired RANK
1 220 35-44 202206 12 6
1 220 35-44 202205 12 5
1 220 35-44 202204 12 4
1 220 35-44 202203 12 3
1 220 35-44 202202 12 2
1 220 35-44 202201 12 1
1 220 35-44 202012 24 24
1 220 35-44 202011 23 23
1 220 35-44 202010 22 22
1 220 35-44 202009 21 21
1 220 35-44 202008 20 20
1 220 35-44 202007 19 19
1 220 35-44 202006 18 18
1 220 35-44 202005 17 17
1 220 35-44 202004 16 16
… … … … … …
1 220 35-44 201901 1 1
This is what I have tried but doesn't work for dates skipping.
RKING Column=
RANKX (
CALCULATETABLE (
VALUES ('tbl'[Date] ),
ALLEXCEPT ( 'tblW', 'tbl'[GP], 'tbl'[ID] ),
'tbl'[AGE] = 'tbl'[AGE],
'tbl'[date] >= start_date && 'tbl'[date] <= end_date // date slicer
),
[Date] ,
,ASC
)
Looking through the code you were trying to make a measure for a visual (For a calcCol the measure is added as well). And as I got a point, you want to show a sum of consequtive months in a matrix for each date in accordance to ID/GP/AGE/DATE I see a following way.
As you know, calculations performs for each row in a matrix and filter the data model according to data presented in matrix rows and columns (slicers as well). So, my idea is -
Get date from matrixRow and use it as max date for the table.
Then use a FILTER(). FILTER() is an iterative function, so it goes throw each row and checks filtering condition - if true row remains if false - not.
I use following filtring conditions:
Get dateInMatrix-dateInACurrentTableRow (for example: 202203-202201= 2 months)
Then check how many rows in the table with min=202201 and max<202203
if there are less rows then date difference then it FALSE() and the row is out of table.
3) The last step is counting of rows it a filtered table.
A measure for matrix:
Ranking =
VAR matrixDate=MAX('table'[DATE])
VAR filteredTable =
FILTER(
ALL('table')
,DATEDIFF(
DATE(LEFT([DATE],4),RIGHT([DATE],2),1)
,DATE(LEFT(matrixDate,4),RIGHT(matrixDate,2),1)
,MONTH
)
=
VAR dateInRow=[DATE]
RETURN
CALCULATE(
COUNTROWS('table')
,'table'[DATE]>=dateInRow
,'table'[DATE]<matrixDate
)
)
RETURN
COUNTROWS(filteredTable)
[![enter image description here][1]][1]
A measure for calcColl:
RankColl =
VAR currentDate=[Start_Date]
Var MyFilt={('Table'[AGE],'Table'[ID],'Table'[GROUP])}
VAR withColl =
ADDCOLUMNS(
CALCULATETABLE(
'table'
,ALL('Table')
,TREATAS(MyFilt,'Table'[AGE],'Table'[ID],'Table'[GROUP])
)
,"dateDiff",
DATEDIFF(
[Start_Date]
,currentDate
,MONTH
)
,"RowsInTable",
VAR dateInRow=[Start_Date]
Var startDate=IF(dateInRow<currentDate,dateInRow,currentDate)
VAR endDay =IF(dateInRow>currentDate,dateInRow,currentDate)
VAR myDates = GENERATESERIES(startDate,endDay,1)
RETURN
COUNTROWS(
CALCULATETABLE(
'Table'
,ALL('Table')
,TREATAS(MyFilt,'Table'[AGE],'Table'[ID],'Table'[GROUP])
,TREATAS(myDates,'Table'[Start_Date])
)
)
)
VAR filtered =
FILTER(
withColl
,[dateDiff]=[RowsInTable]-1 -- for ex.:
-- dateDiff=01/01/2022-01/01/2022=0,
-- but it will be 1 row in the table for 01/01/2022
)
RETURN
CountRows( filtered)

SAS problem: sum up rows and divide till it reach a specific value

I have the following problem, I would like to sum up a column and divide the sum every line through the sum of the whole column till a specific value is reached. so in Pseudocode it would look like that:
data;
set auto;
sum_of_whole_column = sum(price);
subtotal[i] = 0;
i =1;
do until (subtotal[i] = 70000)
subtotal[i] = (subtotal[i] + subtotal[i+1])/sum_of_whole_column
i = i+1
end;
run;
I get the error that I haven't defined an array... so can I use something else instead of subtotal[i]?and how can I put a column in an array? I tried but it doesn't work (data = auto and price the column I want to put into an array)
data invent_array;
set auto;
array price_array {1} price;
run;
EDIT: maybe the dataset I used is helpful :)
DATA auto ;
LENGTH make $ 20 ;
INPUT make $ 1-17 price mpg rep78 ;
CARDS;
AMC Concord 4099 22 3
AMC Pacer 4749 17 3
Audi 5000 9690 17 5
Audi Fox 6295 23 3
BMW 320i 9735 25 4
Buick Century 4816 20 3
Buick Electra 7827 15 4
Buick LeSabre 5788 18 3
Cad. Eldorado 14500 14 2
Olds Starfire 4195 24 1
Olds Toronado 10371 16 3
Plym. Volare 4060 18 2
Pont. Catalina 5798 18 4
Pont. Firebird 4934 18 1
Pont. Grand Prix 5222 19 3
Pont. Le Mans 4723 19 3
;
RUN;
Perhaps I am missing your point but your subtotal will never be equal to 70 000 if you divide by the sum of its column. The maximum value will be 1. Your incremental sum however can be equal or superior to 70 000.
data stage1;
retain _sum 0;
set auto;
_sum = sum(_sum, price);
if _sum < 70000 then output;
run;
proc sql;
create table want as
select t1.*, t1._sum/sum(price) as subtotal
from stage1 as t1;
quit;
subtotal
0.0607268256
0.1310834235
0.2746411058
0.3679017467
0.5121261056
0.5834753107
0.6994325842
0.7851820027
1

Group by and then sum value

I am struggling to get this going and could need some help. I have the following setup:
Order Item Material Value
22 1 100 27,5
22 1 200 27,5
22 1 300 27,5
22 2 100 33
22 3 500 101
26 1 500 88
26 1 600 88
I have duplicate values becaue of the Material, so I want to group by Order, Item and Value and then calculate the total Value in a DAX measure.
After grouping:
Order Item Value
22 1 27,5
22 2 33
22 3 101
26 1 88
The final Value:
Total Measure = 249,5
I tried the following DAX expression for the Total Measure:
Total Measure = Summarize('Table1'; 'Table1'[Order]; 'Table1'[Item]; "Sum Value:"; Sum('Table1'[Value]))
It gives me the error:
Multiple columns cannot be converted to a scalar value
So I tried:
Total Measure = Sumx('Table1'; Summarize('Table1'; 'Table1'[Order]; 'Table1'[Item]; "Sum Value:"; Sum('Table1'[Value])))
But this didnt work either. For every help thanks in advance.
The following code should be what you are looking for
Measure1 =
SUMX (
SUMMARIZE (
Table1;
Table1[Order];
Table1[Item];
Table1[Value];
"TotalSum"; SUM ( Table1[Value] )
);
[Value]
)
In this case, you can simply use the VALUES function instead of SUMMARIZE.
Total Measure = SUMX ( VALUES ( Table1[Value] ), [Value] )
This iterates over each unique Value and adds Value to the sum.

Ranking variables (not observations)

The questionnaire I have data from asked respondents to rank 20 items on a scale of importance to them. The lower end of the scale contained a "bin" in which respondents could throw away any of the 20 items that they found completely unimportant to them. The result is a dataset with 20 variables (1 for every item). Every variable receives a number between 1 and 100 (and 0 if the item was thrown in the bin)
I would like to recode the entries into a ranking of the variables for every respondent. So all variables would receive a number between 1 and 20 relative to where that respondent ranked it.
Example:
Current:
item1 item2 item3 item4 item5 item6 item7 item8 etc.
respondent1 67 44 29 7 0 99 35 22
respondent2 0 42 69 50 12 0 67 100
etc.
What I want:
item1 item2 item3 item4 item5 item6 item7 item8 etc.
respondent1 7 6 4 2 1 8 5 3
respondent2 1 4 7 5 3 1 6 8
etc.
As you can see with respondent2, I would like items that received the same value, to get the same rank and the ranking to then skip a number.
I have found a lot of info on how to rank observations but I have not found out how to rank variables yet. Is there anyone that knows how to do this?
Here is one solution using reshape:
/* Create sample data */
clear *
set obs 2
gen respondant = "respondant1"
replace respondant = "respondant2" in 2
set seed 123456789
forvalues i = 1/10 {
gen item`i' = ceil(runiform()*100)
}
replace item2 = item1 if respondant == "respondant2"
list
+----------------------------------------------------------------------------------------------+
| respondant item1 item2 item3 item4 item5 item6 item7 item8 item9 item10 |
|----------------------------------------------------------------------------------------------|
1. | respondant1 14 56 69 62 56 26 43 53 22 27 |
2. | respondant2 65 65 11 7 88 5 90 85 57 95 |
+----------------------------------------------------------------------------------------------+
/* reshape long first */
reshape long item, i(respondant) j(itemNum)
/* Rank observations, accounting for ties */
by respondant (item), sort : gen rank = _n
replace rank = rank[_n-1] if item[_n] == item[_n-1] & _n > 1
/* reshape back to wide format */
drop item // optional, you can keep and just include in reshape wide
reshape wide rank, i(respondant) j(itemNum)