## Moving average forecast

Solved
Occasional Contributor
Posts: 7

# Moving average forecast

Hi,

As a part of my forecast I am using a moving average based on three observations. Calculating this in SAS I have managed do it only for outcome data and not managed to do it for forecast data. The moving average for a specific month should be the average for the same months three years back. I have tried different kind of syntax but I have found nothing that makes an correct calculation for values after May 2014 (my last outcome).

This syntax creates correct values up until May 2014. After that everything is blank (I have created MA after that in several ways, but never correct).

proc expand data=QQQ out=QQQQ;

id year

by month

convert UUU=UUU_LAG

III=III_LAG

...../

transformout=(reverse movave 3 reverse);

run;

Any ideas/functions? I think it should work from this setup.

Accepted Solutions
Solution
‎09-04-2014 07:10 PM
SAS Employee
Posts: 416

## Re: Moving average forecast

Hello Laasse -

Yes, my data step was only used for creating an example data set.

Thanks,

Udo

proc timedata data=have out=_null_ outarray=want;

var SGI_ROD_FP_ANDEL;

outarray movavg;

do t = 1 to _LENGTH_;

movavg=(SGI_ROD_FP_ANDEL[t-12]+SGI_ROD_FP_ANDEL[t-24]+SGI_ROD_FP_ANDEL[t-36])/3;

if missing(SGI_ROD_FP_ANDEL) then SGI_ROD_FP_ANDEL=movavg;

end;

run;

All Replies
Super Contributor
Posts: 340

## Re: Moving average forecast

Proc expand is rather used to transform data than to use it for forecasting. If you#re actually looking for simple moving averages (not exponentially weighted ones) you could use a data step. Maybe something like this:

Data A;
Input Dateate9. ACTUAL;
Format Date Date9.;
Datalines;
01JAN2000 23
01FEB2000 45
01MAR2000 12
01APR2000 89
01MAY2000 23
;
Run;

Data A_Forecast (Drop=dummy);
Retain dummy;
Set A;
dummy=Sum(dummy,ACTUAL,-Lag3(ACTUAL));
Mov_Ave_3_GD=dummy/3;
Run;

Super Contributor
Posts: 340

## Re: Moving average forecast

Occasional Contributor
Posts: 7

## Re: Moving average forecast

I have seen that kind of solution. The problem however is that my MA is not as simple as that one (they are still simple but not enough..). For June 2014 I want the average of June 2011-2013. And so on, thus I don´t just want the average of the three last months. How can I add a by statement and an ID variable into your solution?

Super User
Posts: 10,035

## Re: Moving average forecast

Give us an example to illustrate your problem .

Super Contributor
Posts: 340

## Re: Moving average forecast

I might be entirely wrong, but I think:

%Let Periods=3;
%Let Multiplier=12; /* 12 months */

%Let Comb_Lag=%Eval(&Periods.*&Multiplier.);

Data A (Drop=i j k);
Format Date Date9.;
Do k=1 to 3;
Do j=1 to 5;
Do i=1 to 12;
Date=MDY(i,1,j+2000);
ACTUAL=Round(Normal(1)*k+20); /* k as Standard Deviation */
ID=k;
Output;
End;
End;
End;
Run;

/* "simple" seasonal (??) moving average */
Data A_Forecast (Keep=ID Date ACTUAL Mov_Ave);
Set A;
By ID;
Array dummy{*} dummy1-dummy12;
Array dummy_sum{*} dummy_sum1-dummy_sum12;
Array dummy_drop {*} dummy_drop1-dummy_drop12;
Retain dummy_sum1-dummy_sum12;
Do i=1 To 12;
If Month(Date) eq i Then Do;
dummy{i}=ACTUAL;
dummy_drop{i}=Lag&Comb_Lag.(ACTUAL);
End;
End;
If First.ID Then Do;
count=0;
Do i=1 To 12;
dummy_sum{i}=0;
End;
End;
count+1;
If count gt &Comb_Lag. Then Do;
Do i=1 To 12;
dummy_sum{i}=Sum(dummy_sum{i},dummy{i},-dummy_drop{i});
End;
End;
Else Do;
Do i=1 To 12;
dummy_sum{i}=Sum(dummy_sum{i},dummy{i});
End;
End;

If count ge &Comb_Lag. Then Do;
Do i=1 To 12;
If not Missing (dummy{i}) Then dummy_sum_act=dummy_sum{i};
End;
Mov_Ave=dummy_sum_act/&Periods.;
End;
Run;

Retain Date ID Mve_Ave;
Set A_Forecast;
By ID;
If Last.ID Then Do;
Output;
Date=IntNX('month',Date,1,'same');
ACTUAL=.;
Output;
End;
End;
Output;
Run;

Occasional Contributor
Posts: 7

## Re: Moving average forecast

Thank you user24 feb. I will however start by looking at udo@sas' answer and method.

Occasional Contributor
Posts: 7

## Re: Moving average forecast

My summer vacation starts today (earlier than planned...). I will be back in about two and half week and then try to solve this. I appreciate your help!

SAS Employee
Posts: 416

## Re: Moving average forecast

Hello -

After returning from vacation you may want to look into PROC TIMEDATA to accomplish this task.

See example below.

Thanks,

Udo

data have;

set sashelp.air end=last;

if last then do i=0 to 12;

date=intnx('month',"01DEC60"d, i);

if i ge 1 then air=.;

output;

end;

else output;

drop i;

run;

proc timedata data=have out=_null_ outarray=want;

id date interval=MONTH;

var air;

outarray movavg;

do t = 1 to _LENGTH_;

movavg=(air[t-12]+air[t-24]+air[t-36])/3;

end;

run;

Occasional Contributor
Posts: 7

## Re: Moving average forecast

Thank you udo@sas. I couldn´t really start with this after returning from my vacation, but now I can find some time and I have already found some use of your answer. However I'm not there yet. I think I don't need your kind of data step because I already have a date variable manad (YYMMN6. 200801-201812) and of course my variable of interest SGI_ROD_FP_ANDEL (with values from 200801 until 201405). When writing my proc timedata step I'm doing like this:

proc timedata data=have out=_null_ outarray=want;

var SGI_ROD_FP_ANDEL;

outarray movavg;

do 1 to _LENGTH_;

movavg=(SGI_ROD_FP_ANDEL[t-12]+SGI_ROD_FP_ANDEL[t-24]+SGI_ROD_FP_ANDEL[t-36])/3;

end;

run;

Then I got movavg values from 201101 until 201505. My objective is however to get values from 201406 until 201812. Hence I want moving average values that depend of a mix of SGI_ROD_FP_ANDEL values and movavg values and some that only depends of movavg values. Is that possible? When I substitute "_LENGTH_" for something else, it simply doesn't work. What I'm doing wrong?

Solution
‎09-04-2014 07:10 PM
SAS Employee
Posts: 416

## Re: Moving average forecast

Hello Laasse -

Yes, my data step was only used for creating an example data set.

Thanks,

Udo

proc timedata data=have out=_null_ outarray=want;

var SGI_ROD_FP_ANDEL;

outarray movavg;

do t = 1 to _LENGTH_;

movavg=(SGI_ROD_FP_ANDEL[t-12]+SGI_ROD_FP_ANDEL[t-24]+SGI_ROD_FP_ANDEL[t-36])/3;

if missing(SGI_ROD_FP_ANDEL) then SGI_ROD_FP_ANDEL=movavg;

end;

run;

🔒 This topic is solved and locked.