DAX for rolling seven day average to pivot chart by year - excel

I'm trying to create a single pivot chart that will show separate years of data on the same date axis for a rolling 7-day average.
So, the x-axis will be text, 01-Jan to 31-Dec, and each year will be a separate series:
It has to be a text x-axis, as 01-Jan will be a category containing data for 01-Jan-2018, 01-Jan-2019, 01-Jan-2020...
In theory, the pivot table setup would have the column (series) as the Year, and the x-Axis (labels) as the date label (column Date).
The values are then from the DAX expression that creates the rolling 7-day average.
The source data (tblSource) has a single column of dates (Date2) that rolls over across years and has the column Year to break it down in the pivot.
The daily value is the one that is averaged (itself and the previous six days).
The 7-day average I normally use in DAX doesn't work here.
I need to have the Date column actually in the pivot rather than Date2, as the axis needs to be text to allow for multiple date years on the same x-axis point, but I can't get a DAX formula to work.
The other consideration is that the formula can't just consider a single year, as the rolling seven day average for 01-Jan-2018 includes the previous six days of 2017, for example.
This is the formula I usually use, but I can't manage to tweak it!
AVERAGEX (
DATESINPERIOD ( tblSource[Date2], LASTDATE ( tblSource[Date2] ), -7, DAY ),
[Sum of Daily Value]
)
But this is the output I get, and nothing has been averaged. I think it's because Date2 is being pivoted off Date, but I'm not sure how I get around that?
Can anybody offer me any help?
It's quite a frustrating problem as it would be trivial for me to do it using code, or doing it manually, but I really am trying to get better at DAX!
Thanks in advance!
Phil.
Update: Thanks to Joao for this.
=VAR d = MAX(tblSource[Date2])
RETURN CALCULATE(AVERAGE(tblSource[Daily Value]),
ALL(tblSource[Date]),
DATESINPERIOD(tblSource[Date2], d, -7, day),tblSource[Year]>0)
I had to use MAX rather than SELECTVALUE as Excel seems to lack that functionality.
I also had to unfilter the Year, so that the rolling average could be calculated from the previous year's date where neccessary.
Thanks.

When you run that measure, your table is being filtered by the date text at each point, so when you pass/create the DATESINPERIOD filter, it creates a table with the last 7 dates, but only one of them is actually available (the one relevant to your current data point).
You need to clear the filters on the table so that you have all the dates available, in order for you average to work. You can achieve this by changing the measure slightly:
VAR d = SELECTEDVALUE(tblSource[Date2])
RETURN CALCULATE(AVERAGE(tblSource[Daily Value]),
ALL(tblSource[Date]),
DATESINPERIOD(tblSource[Date2], d, -7, day))

Related

DAX Measure no longer calculates accurately if I sort an axis by another column?

I'm having some trouble creating a DAX Measure in PowerBI that will group sales by quarter, but still sort correctly. Our sales data is received cumulatively and once a quarter. I've created the following DAX Measure to calculate the quarterly sales:
Quarterly Sales = SWITCH(
SELECTEDVALUE(FactSales[Quarter]),
"Q1 2018/19",CALCULATE(sum(FactSales[Quantity]),FactSales[Quarter]="Q1 2018/19"),
"Q2 2018/19",CALCULATE(sum(FactSales[Quantity]),FactSales[Quarter]="Q2 2018/19")-CALCULATE(sum(FactSales[Quantity]),FactSales[Quarter]="Q1 2018/19"),
"Q3 2018/19",CALCULATE(sum(FactSales[Quantity]),FactSales[Quarter]="Q3 2018/19")-CALCULATE(sum(FactSales[Quantity]),FactSales[Quarter]="Q2 2018/19"),
"Q4 2019/20",CALCULATE(sum(FactSales[Quantity]),FactSales[Quarter]="Q4 2018/19")-CALCULATE(sum(FactSales[Quantity]),FactSales[Quarter]="Q3 2018/19"),
"Q1 2019/20",CALCULATE(sum(FactSales[Quantity]),FactSales[Quarter]="Q1 2019/20")
)
The problem is, while this calculates accurate numbers, it chart sorts this alphabetically, so the two Q1s are beside each other. when I try to sort the Quarter column by a Sorting dummy column, the calculations then all become out of wack and are no longer accurate.
I feel like there must be an easy way to fix this, but I can't figure out how to do it. Thank you in advance for any assistance!

Getting workdays for the year in Power Pivot DAX

I need to use the full year's work days in my DAX calculation, but I can't figure out how to get DAX to do that. I have two tables,
1) sales with their respective dates
2) work days table, with end of month and the month's respective work days
I created the relationship between the two, based on the date, and it works, however DAX captures workdays only for the month's where there were sales. How do I get the full year's sum?
As an example, these are the two tables I created:
and connected them as follows:
I then added a calculated field with the following DAX:
=CALCULATE(
SUM(tWorkdays[Days]),
FILTER(
tSales,
YEAR(tSales[Date]) = YEAR(MAX(tSales[Date]))
)
)
and built a pivot table like so:
As you can see, it just captures workdays for the months where there were sales, but I need the entire total, regardless if there were any sales or not.
What can I do to fix this?
I'm not positive about the details, but it has something to do with ALL(), EXCEPT(), and VALUES()
A matter of context, as they say in DAX
https://powerpivotpro.com/2011/06/precedence-part-3-allexcept-vs-all-w-values/
And another explanation:
https://www.sqlbi.com/articles/using-allexcept-versus-all-and-values/

Calculate average based on a value column (count) in a pivot table

I'm looking a way to add an extra column in a pivot table that that averages the sum of the count for the months ("Count of records" column) within a time period that is selected (currently 2016 - one month, 2017 - full year, 2018 - 5 month). Every month would have the same number based on the year average, needs to be dynamically changing when selecting different period: full year or for example 4 months. I need the column within the pivot table, so it could be used for a future pivot chart.
I can't simply use average as all my records appear only once and I use Count to aggregate those numbers ("Count of records" column).
My current data looks like this:
The final result should look like this:
I assume that it somehow can be done with the help of "calculated filed" option but I couldn't make it work now.
Greatly appreciate any help!
Using the DataModel (built in to Excel 2013 and later) you can write really cool formulas inside PivotTables called Measures that can do this kind of thing. Take the example below:
As you can see, the Cust Count & Average field gives a count of transactions by month but also gives the average of those monthly readings for the subtotal lines (i.e. the 2017 Total and 2018 Total lines) using the below DAX formula:
=AVERAGEX(SUMMARIZE(Table1,[Customer (Month)],"x",COUNTA(Table1[Customer])),[x])
That just says "Summarize this table by count of the customer field by month, call the resulting summarization field 'x', and then give me the average of that field x".
Because DAX measures are executed within the context of the PivotTable, you get the count that you want for months, and you get the average that you want for the yearly subtotals.
Hard to explain, but demonstrates that DAX can certainly do this for you.
See my answer at the following link for an example of how to add data to the DataModel and how to subsequently write measures:
Using the Excel SMALL function with filtering criteria AND ignoring zeros
I also recommend grabbing yourself a book called Supercharge Excel when you learn to write DAX by Matt Allington, and perhaps even taking his awesome online course, because it covers this kind of thing very well, and will save you significant head-scratching compared to going it alone.

Spotfire Bargraph to show Avg Quality by year for previous years and by month for current year

I have a bargraph which shows the quality of my data for each month. As the data is growing over the years, the graph is getting messy. So, i would like to show Avg Quality by year for all those months in Previous years but monthly for the current year.
Can any one help me how to achieve this.
Thanks,
-Dileep
This needs to be separated into two charts, or it just won't be legible. I'd suggest:
Creating an AVG by Year bar chart graph for all your data
Creating a details visualization of the above Yearly Average data which shows the 12 months of that year with SUM() as your aggregation method. Be sure to have YEAR > Month on your category axis
Thus, if you need to compare 1, 2, 3 or all the years by month you can select them all, or just the ones you want.
I was able to do it with the help of some calculated columns. To help explain, let's assume the value column in your data set is called Value and the date column in your data set is called ValueDate. I created some fictional data that extends into April, 2017 to help illustrate the solution.
Insert a calculated column to classify whether or not the date in each row is in the current year or not. I'm going to call the column DateGrouping.
CASE WHEN Year(DateTimeNow())=Year([ValueDate]) THEN "Monthly" WHEN Year(DateTimeNow())>Year([ValueDate]) THEN "Yearly" END AS [DateGrouping]
Insert a calculated column that tells us the last date of the month for ValueDate. E.g., if the date in the row is 4/10/2015, the last day of the month for the day in that row is 4/30/2015. If the date in the row is 7/8/2013, the last day of the month for the date in that row is 7/31/2013. We'll call this column LastDateOfMonth.
DateAdd("day",-1,date(Year([ValueDate]),Month(DateAdd("month",1,[ValueDate])),1))
Insert a calculated column that tells us the last date of the year for ValueDate. Of course, it's just Dec. 31 of ValueDate's year. Call this column LastDateOfYear.
Date(Year([ValueDate]),12,31)
Finally, we utilize the previous three calculated columns to add a calculated column for the date value we want to plot. You are wanting to plot by month for the current year, and by year for prior years.
CASE [DateGrouping] WHEN "Monthly" THEN [LastDayOfMonth] WHEN "Yearly" THEN [LastDateOfYear] END
On my value axis is the Value column, which I'm aggregating as an Average. On my category axis is the calculated DatePlot column -- I set the category axis to Categorical Scale. And I'm coloring by the calculated DateGrouping column to offer a visual cue that the data is aggregated differently over time.
Now, should this be done? There are certainly some pitfalls. You can't make the category axis Continuous Scale or else you'll see all the empty months when we're lumping prior years into Dec. 31. On the other hand, gaps are good visually when there is no data for a given period. So I don't know. But I pictured what you were asking and decided to try it. Buyer beware!

Spotfire: Select data from column based on criteria

I have a data table in Spotfire which contains two columns I'm interested in: Time (31/01/2015 for example), and Value (integer).
I want the most recent date (e.g. December 2015) to be set as the current time. Then I want to select Value based on previous 1 month, 3 months, 6 months etc. So if I want all the values for past 6 months it should Sum(Values) for Dec.2015, November.2015, October.2015, September.2015, August.2015 and return that.
So far I've only been able to accomplish this by manually performing the task in Excel before I insert it into Spotfire so is there any way to create a calculated column for each of the periods I want? (Past month, 3 months etc.)
There's likely a number of ways to solve this, but I'm going to give one suggestion and we'll see how it fits your specific case.
You can add a calculated column for each timespan you are interested in, defined like this:
Sum(if (DateAdd('month', 3, [Time]) >= Max([Time]), [Value], null))
This example would get you a column with all the values that have occured in the past 3 months, replace the number 3 in there to modify to the timespans you are interested in. A full sum of the calculated column would get you the total for that timespan.
Might be nicer to use a boolean column instead of duplicating the value column. Then your calculated columns would be defined as:
DateAdd('month', 3, [Time]) >= Max([Time])
When calculating totals you would then use an if statement using the calculated column, like this:
Sum(if([3Months],[Value],null))
where [3Months] is a boolean column.

Resources