Subscribe Bookmark RSS Feed

Calculate Moving Average Using Last 3 Time Periods

Risslemc

Occasional Contributor

Joined:

Apr 26, 2017

I have a set of data with three columns; Customer, TimePeriod, and Quantity. TimePeriod is in the format of yyyymm. I'm trying to determine a formula to calculate a "rolling average" over the last 3 time periods, across all customers.

 

For example, In my row labeled 201704, I want a formula to return the average Quantity for all records from 201703, 201702, and 201701. The TimePeriod can occur multiple times in the data (by Customer), which makes it a little more complicated.

 

Any suggestions?

1 ACCEPTED SOLUTION

Accepted Solutions
txnelson

Super User

Joined:

Jun 22, 2012

Solution

Here is your formula

dt = Current Data Table();
tp = :timeperiod;
tmp = Date Increment(
	Date MDY( Num( Substr( :timeperiod, 5, 2 ) ), 1, Num( Substr( :timeperiod, 1, 4 ) ) ),
	"Month",
	-1
);
lagtp1 = Char( Year( tmp ) ) || Try( Substr( "0", Length( Char( Month( tmp ) ) ), 1 ), "" ) ||
Char( Month( tmp ) );
tmp = Date Increment(
	Date MDY( Num( Substr( :timeperiod, 5, 2 ) ), 1, Num( Substr( :timeperiod, 1, 4 ) ) ),
	"Month",
	-2
);
lagtp2 = Char( Year( tmp ) ) || Try( Substr( "0", Length( Char( Month( tmp ) ) ), 1 ), "" ) ||
Char( Month( tmp ) );
Mean(
	:Quantity[dt << get rows where( :timeperiod == tp | :timeperiod == lagtp1 | :timeperiod == lagtp2 )
	]
);
Jim
8 REPLIES
txnelson

Super User

Joined:

Jun 22, 2012

Solution

Here is your formula

dt = Current Data Table();
tp = :timeperiod;
tmp = Date Increment(
	Date MDY( Num( Substr( :timeperiod, 5, 2 ) ), 1, Num( Substr( :timeperiod, 1, 4 ) ) ),
	"Month",
	-1
);
lagtp1 = Char( Year( tmp ) ) || Try( Substr( "0", Length( Char( Month( tmp ) ) ), 1 ), "" ) ||
Char( Month( tmp ) );
tmp = Date Increment(
	Date MDY( Num( Substr( :timeperiod, 5, 2 ) ), 1, Num( Substr( :timeperiod, 1, 4 ) ) ),
	"Month",
	-2
);
lagtp2 = Char( Year( tmp ) ) || Try( Substr( "0", Length( Char( Month( tmp ) ) ), 1 ), "" ) ||
Char( Month( tmp ) );
Mean(
	:Quantity[dt << get rows where( :timeperiod == tp | :timeperiod == lagtp1 | :timeperiod == lagtp2 )
	]
);
Jim
Risslemc

Occasional Contributor

Joined:

Apr 26, 2017

Thank you very much for your reply.

 

I'm very new to scripting. Is there a way for the mean to be output in a new column, by row? So as the script determines the mean over the last 3 timeperiods it will display that for each row in a new column?

 

Additionally, is there an issue with that script at the beginning of the data set? When there's no lagtp1 or lagtp2 for the very first date? 

txnelson

Super User

Joined:

Jun 22, 2012

What I gave you is a new formula that is intended to be used in a new column, that will create a new value for each row.

In the data table, go to the pull down menu

     Cols==>New Column

Name the column whatever you want

In the lower left hand corner, click on

     Column Properties

Select Formula

Double click on the blue box that says "No Formula"

In the window that opens, paste in the formula

 

 

Jim
Risslemc

Occasional Contributor

Joined:

Apr 26, 2017

Jim - Thank you for your patience.

 

I added that formula into a new column, as you guided, but I get the same repeating value down the whole column.

I would like the formula to just give me the mean for the last 3 time periods of that row.

 

For example, the Mean record from 201704 should only average the last 3 time periods from April 2017 (201704, 201703, 201702). The next row from 201705 should have a different average consisting of the last 3 time periods from May 2017 (201705, 201704, 201703).

 

Thoughts? 

 

txnelson

Super User

Joined:

Jun 22, 2012

The formula that I gave you takes a look at the year/month value for a given row.  It then finds what the value 1 month prior is, and the value 2 months prior would be.  It then finds the mean for all rows in the data table that have the year/month value for any of the 3 calculated year/month values.

Therefore, any row that has a year/month value of, let's say, 201705, would find the average quanity of all of the rows in the data table that are found to have the value of 201705, 201704 or 201703.  My limited test case worked for this.  Please note, the physical order of the rows in the data table are not of importance.  The formula finds all of the rows in the entire data table that match the 3 time periods for a given row.

If you could provide me with a sample data table, I can look further into this.  Or, maybe my interpretation of what you are asking is not correct.

Jim
Risslemc

Occasional Contributor

Joined:

Apr 26, 2017

You were correct! It must have been user error on my end :-)

If I want the means separated by customer, let's say 'Customer' is in its own column to reference, is that possible?

So then the output column will only calculate the mean for the last 3 timeperiods for the customer in that row.

 

 

txnelson

Super User

Joined:

Jun 22, 2012

Here is the extension of the formula with the Customer added in

dt = Current Data Table();
tp = :timeperiod;
cus = :Customer;
tmp = Date Increment(
	Date MDY( Num( Substr( :timeperiod, 5, 2 ) ), 1, Num( Substr( :timeperiod, 1, 4 ) ) ),
	"Month",
	-1
);
lagtp1 = Char( Year( tmp ) ) || Try( Substr( "0", Length( Char( Month( tmp ) ) ), 1 ), "" ) ||
Char( Month( tmp ) );
tmp = Date Increment(
	Date MDY( Num( Substr( :timeperiod, 5, 2 ) ), 1, Num( Substr( :timeperiod, 1, 4 ) ) ),
	"Month",
	-2
);
lagtp2 = Char( Year( tmp ) ) || Try( Substr( "0", Length( Char( Month( tmp ) ) ), 1 ), "" ) ||
Char( Month( tmp ) );
Mean(
	:Quantity[dt << get rows where( ( :timeperiod == tp | :timeperiod == lagtp1 | :timeperiod == lagtp2 ) &
	:Customer == cus)
	]
);
Jim
Risslemc

Occasional Contributor

Joined:

Apr 26, 2017

Thank you again for all your help!

 

That's exactly what I was looking for.

 

-Matt