Moving Average Template in Power Query - indexing

I am new to Power Query and I'm trying to create a query template that applies a 3 moving average to the volume and sales for the next 3 weeks grouped by weekday for each product.
My input table looks like this.
Note: I didn't include all the data but there is data for each weekday (Mon, Tue, Wed, Thu, Fri, Sat, Sun) and there are more products.
Below are the steps that I've been doing:
.Sort the data first by call type and then by weekday.
.Then grouped the rows and create an index for each product-weekday with the next code:
'''#"Grouped Rows" = Table.Group(#"Sorted Rows", {"product", "weekday"}, {{"Index", each
Table.AddIndexColumn(_,"Index", 1,1), type table}}),
#"Expanded Index" = Table.ExpandTableColumn(#"Grouped Rows", "Index", {"date", "volume", "sales",
"Index",} , {"Index.date", "Index.volume", "Index.sales",
"Index.Index",}'''
Then I apply the 3 moving Average to the volume:
''' step1 = Table.AddColumn(#"Expanded Index", "Average_vol", each if [Index.Index] > 2 then List.Average(List.Range(#"Expanded Index"[Index.volume], _[Index.Index] -3, 3)) else null, type number'''
So now I have this:
[![!['''][2]][2]
*the highlighted cells are the moving average expected for the next week.
It's working but now I need to include the numbers in yellow for the next week.
So now I'm stuck on that step and I need to create the template.
Do you know how can I apply the moving average for the next 2 weeks including the calculated numbers for the next week(yellow numbers)?
Output
So, what I'm trying to do is create the moving average for the next week the use this number as input to calculated the moving average for the 2nd week and do the same to calculate the 3rd week

Can you just add 3 three custom columns with = Date.AddDays([date],7)= Date.AddDays([date],14)= Date.AddDays([date],21)
Then merge the data on top of itself three times using [product] and [date] matching against [product] and either [date1] or [date2] or [date3]. Expand the merged data to pull out the sales and volume from those 3 weeks. After the expands, each row will have that weeks own number, along with the numbers from the next 3 weeks. Average them
Note this is not going to take the moving average from the first week and somehow use that in the following weeks calculations

Related

Create chart where the columns of the data set are the categories - Report Builder 3.0

I have a very simple chart that I am wanting to add but I can't for the life of me figure it out. The chart is referencing a dataset that returns data like this. It is calculating the sum of each Location and then using Rollup to produce a Total Count for each Week Column
Location CurrentWeek PreviousWeek 2WeeksAgo
======== =========== =========== ===========
North 5 6 3
South 4 3 1
East 8 2 3
West 2 7 0
Total 19 18 7
What I am wanting to do is have the X Axis (horizontal) represented by the CurrentWeek, PreviousWeek, 2WeeksAgo columns and plot the "Total" values from each respective column.
Adding Snip...
Sample Chart
Thanks for adding the image.
So we have a few steps to get to where we need to be - first, we need to transform the data into a format that's easier and more scalable to work with (if we ever add a "3 weeks ago" column, we don't want to have to rework everything). The desired format is:
Date Amount
Current Week 19
1 week ago 18
2 weeks ago 17
Personally - instead of naming stuff "current week", "1 week ago" etc., I would have a WeeksPrior column where 0 would mean the current week, 1 would mean a week ago and so on.
Anyways, to get from your sample table to the more standardized input, we have to use an unpivot (these always hurt my brain, but the docs have some good examples you can use).
SELECT
*
, ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) AS Ordinal
--this is hacky, but ordering by (select null) allows us to assign a row number by the default order
FROM (SELECT 'Total' AS Location, 19 AS CurrentWeek, 18 AS PreviousWeek, 7 AS [2WeeksAgo]) x
--This is the test data, replace this with your actual query
UNPIVOT (Value FOR Date IN ([CurrentWeek], [PreviousWeek], [2WeeksAgo])) y
--This unpivots the test data, converting the separate columns into a single [Date] column, and assigning the values to the [Value] column.
This will spit out the following:
Location Value Date Ordinal
Total 19 CurrentWeek 1
Total 18 PreviousWeek 2
Total 7 2WeeksAgo 3
From here, we add the data to the chart. This is pretty straighforward, but there are a few "gotchas" to be wary of.
First, we'll add the Value column as a chart value, and the Ordinal column as a category group.
Let's see what the chart looks like right now by running the report.
Well, it's getting there, but we want our labels on the bottom. To do this, we go into the Ordinal category group's properties and switch the label to the date column. Make sure you're still sorting by Ordinal, since SSRS doesn't know what "1 week ago" means relative to "Current Week", and will sort alphabetically or randomly if you don't tell it to sort by ordinal.
We can also clean up the chart a bit by removing the legend and changing the major tick mark line style to "solid" on the horizontal axis., leaving us something that looks like this:
Adding a label to the vertical axis would probably also help readability, as would adding hover-text to the points on the chart.

Calculating mean of a specific column by specific rows

I have a dataframe that looks like in the pictures.
Now, I want to add a new column that will show the average of power for each day (given the data is sampled every 5 minutes), but separately for when it is day_or_night (day = 0 in the column, night = 1). I've gotten this far:
train['avg_by_day'][train['day_or_night']==1] = train['power'][train['day_or_night']==1].mean()
train['avg_by_day'][train['day_or_night']==0] = train['power'][train['day_or_night']==0].mean()
but this just adds the average of all the power values that correspond to day, or similarly - night, which isn't what I'm after: a specific average for each day/night separately.
I need something like: train['avg_by_day'] == train.power.mean() when day == 1 and day_or_night == 1, and this for each day.
So you want to group the dataframe by day and day_or_night and create a new column with mean power values for each group:
train['avg_by_day'] = train.groupby(['day','day_or_night'])['power']\
.transform('mean')
Maybe you should also include year and month in the grouping columns because otherwise it's going to group the 1st day of every month together, same for the 2nd day and so on.

How to show last 13 months in X axis based on single slicer selection?

EDIT: As this is an old question, the intended solution is supported by the relative date slicer in Power BI as seen here.
I am building a rolling 13 month net revenue chart and I've came across a requirement to show the last 13 month in x axis based in what month (YYYYMM) the user selected in a YYYYMM slicer.
The chart below is the one I want:
In order to get the intended behaviour, currently I need to select each one of the 13 month in YYYYMM slicer:
Any ideas on how I can get this to work in Power BI so that the user just have to select the base month?
Thanks in advance,
Cristhian.
Let's say you have a table data(date, value).
Add a table datefilter(date) with dates you want to select. Add a slicer by this date.
Add a calculated column to data : date2 = DATEADD('data'[date].[Date],13,MONTH)
Add this measure:
current = IF(AND(
MAX('data'[date]) < MAX('datefilter'[date]),
MAX('data'[date2]) > MAX('datefilter'[date])),1,0)
filter your visualisation by current is 1.

Set ascendnig X axis in a QlikView chart

I have a qlikview chart where the dimension is the week of a date.
So i get a groupped sum of the values for weeks.
Its good but when its start from the middle of the year it will start ascending e.g.:
y->2 5 2
x->22 23 24 etc
but i want:
y->2 5 2
x->1 2 3
But I tried to change dimension somehow but all faild, I tried at the sort tab some expression or the layout but i simply cant find to to replace the x-axis values.
So now the dimension (x) is Calender_Week of the date. but it returns 0-52 the week of the year.
But I dont want to show this 0-52 I want a static numbers.
If week 26-32 then 1-2-3-4-5-6-7
If week 12-13 then 1-2
If week 51-52-01-02 then 1-2-3-4
The reason that you cannot sort the values correctly is because the week number is just a value between 1 and 53. You cannot specify a sort order since there is no way of telling which year the week number belongs to.
However, there is a way to resolve this. In the following example, let's assume that I have my data table MyData defined as follows:
MyData:
LOAD
*
INLINE [
CalendarDate, Result
15/12/2014, 5
16/12/2014, 6
22/12/2014, 10
29/12/2014, 20
30/12/2014, 30
05/01/2015, 20
];
I have another table which loads from MyData and derives the week number:
MyChartData:
NOCONCATENATE
LOAD
WeekNumber,
Sum(Result) as Result
GROUP BY WeekNumber;
LOAD
Week(date#(CalendarDate,'DD/MM/YYYY')) as WeekNumber,
Result
RESIDENT MyData;
DROP TABLE MyData;
If I chart these data I have the problem of sorting (at first glance it seems okay, but in this instance week 1 should come after week 52):
Now, to solve this we need another way to sort the data but still keep it grouped at a weekly level. As I have the original calendar date, I can create a new field which does just that: a concatenation of week number and year (i.e. YYYYWW):
NOCONCATENATE
LOAD
WeekNumber,
YearWeek,
Sum(Result) as Result
GROUP BY WeekNumber, YearWeek;
LOAD
WeekNumber,
(WeekYear * 100 + WeekNumber) as YearWeek,
Result;
LOAD
Week(date#(CalendarDate,'DD/MM/YYYY')) as WeekNumber,
WeekYear(date#(CalendarDate,'DD/MM/YYYY')) as WeekYear,
Result
RESIDENT MyData;
If I then swap out WeekNumber from my chart and replace it with WeekYear then things are looking better:
Edit - now to relabel the dimension values
To relabel the YearWeek values so that they are just shown as an relative index (or "column" number), we can use a calculated dimension and utilise the aggr function as follows:
=aggr(RowNo(), YearWeek)
This then results in a chart as follows:
The advantage to this method is that whichever selections you make in your QlikView document, the relative index will remain contiguous even though the underlying data could be discontinuous. Furthermore this does not hard-code the index into the data model.

SQL Statement for MS Access Query to Calculate Quarterly Growth Rate

I have a table named "Historical_Stock_Prices" in a MS Access database. This table has the columns: Ticker, Date1, Open1, High, Low, Close1, Volume, Adj_Close. The rows consist of the data for each ticker for every business day.
I need to run a query from inside my VB.net program that will return a table in my program that displays the growth rates for each quarter of every year for each ticker symbol listed. So for this example I would need to find the growth rate for GOOG in the 4th quarter of 2012.
To calculate this manually I would need to take the Close Price on the last BUSINESS day of the 4th quarter (12/31/2012) divided by the Open Price of the first BUSINESS day of the 4th quarter (10/1/2012). Then I need to subtract by 1 and multiply by 100 in order to get a percentage.
The actual calculation would look like this: ((707.38/759.05)-1)*100 = -6.807%
The first and last days of each quarter may vary due to weekend days.
I cannot come up with the correct syntax for the SQL statement to create a table of Growth Rates from a table of raw Historical Prices. Can anyone help me with the SQL statment?
Here's how I would approach the problem:
I'd start by creating a saved query Access named [Stock_Price_with_qtr] that calculates the year and quarter for each row:
SELECT
Historical_Stock_Prices.*,
Year([Date1]) AS Yr,
Switch(Month([Date1])<4,1,Month([Date1])<7,2,Month([Date1])<10,3,True,4) AS Qtr
FROM Historical_Stock_Prices
Then I'd create another saved query in Access named [Qtr_Dates] that finds the first and last business days for each ticker and quarter:
SELECT
Stock_Price_with_qtr.Ticker,
Stock_Price_with_qtr.Yr,
Stock_Price_with_qtr.Qtr,
Min(Stock_Price_with_qtr.Date1) AS Qtr_Start,
Max(Stock_Price_with_qtr.Date1) AS Qtr_End
FROM Stock_Price_with_qtr
GROUP BY
Stock_Price_with_qtr.Ticker,
Stock_Price_with_qtr.Yr,
Stock_Price_with_qtr.Qtr
That would allow me to use the following query in VB.NET (or C#, or Access itself) to calculate the quarterly growth rates:
SELECT
Qtr_Dates.Ticker,
Qtr_Dates.Yr,
Qtr_Dates.Qtr,
(([Close_Prices]![Close1]/[Open_Prices]![Open1])-1)*100 AS Qtr_Growth
FROM
(
Historical_Stock_Prices AS Open_Prices
INNER JOIN Qtr_Dates
ON (Open_Prices.Ticker = Qtr_Dates.Ticker)
AND (Open_Prices.Date1 = Qtr_Dates.Qtr_Start)
)
INNER JOIN
Historical_Stock_Prices AS Close_Prices
ON (Qtr_Dates.Ticker = Close_Prices.Ticker)
AND (Qtr_Dates.Qtr_End = Close_Prices.Date1)