2010-03-17 143 views
3

惠傢伙,計算SAS中的移動平均數/ stdev?

我包括截圖,以幫助澄清我的問題:

http://i40.tinypic.com/mcrnmv.jpg

我正試圖計算某種移動平均值和移動標準偏差。問題是我想計算實際值的變化係數(stdev/avg)。通常這是通過計算過去5年的stdev和avg來完成的。但是有時候我的數據庫中會有觀察,我沒有過去5年的信息(可能只有3,2等)。這就是爲什麼我需要一個代碼來計算avg和stdev,即使在整個5年內沒有任何信息。另外,正如你在觀察中看到的那樣,有時我有超過5年的信息,當這種情況下我需要某種移動平均值,這使得我可以計算過去5年的平均值和標準偏差。因此,如果一家公司有7年的信息,我需要一些代碼來計算1997年(到1991 - 1996年),1998年(到1992 - 1997年)和1999年(1993 - 1998年)的平均值和stdev。

因爲我不是很熟悉SAS命令,它看起來應該(非常非常粗略的),如:

set var 
if year = i then stdev=stdev(year(i-6) untill year(i-1)) and average = avg(year(i-6) untill year(i-1)) 

或像這樣的東西,我真的不知道,我要去嘗試和看着辦吧但如果我自己找不到它,值得發佈。

謝謝!

回答

0

爲了便於閱讀,我會提倡proc sql。使用張仲的數據,你可以試試下面的例子:

/* test data */ 
data one; 
    input symbol $ value date :date9.; 
    format date date9.; 
cards; 
ABP1 -0.025 18feb1997 
ABP1 0.05 25feb1998 
ABP1 -0.025 05mar1999 
ABP1 0.06 20mar2000 
ABP1 0.25 05mar2001 
ABP1 0.455 07mar2002 
ABP1 0.73 25feb2003 
ABP1 1.01 19feb2004 
ABP1 1.25 16feb2005 
ABP1 1.65 09feb2006 
ABP1 1.87 08feb2007 
ABT 0.555 14jan1991 
ABT 0.6375 14jan1992 
ABT 0.73 16jan1993 
; 
run; 

proc sql; 
    create table two as 
    select distinct 
     a.symbol, 
     b.value, 
     year(a.date) as year, 
     b.date as date5 
    from 
     one a, 
     one b 
    where 
      a.symbol=b.symbol 
     and intck('year',b.date,a.date) between 1 and 5 
    order by 
     a.symbol, 
     year, 
     date5; 
quit; 

proc sql; 
    create table three as 
    select distinct 
     symbol, 
     year, 
     count(symbol) as n5, 
     avg(value) as avg5, 
     std(value) as std5 
    from 
     two 
    group by 
     symbol, 
     year; 
quit; 
1

這是一種方法。希望這可以幫助。

/* test data */ 
data one; 
    input symbol $ value date :date9.; 
    format date date9.; 
cards; 
ABP1 -0.025 18feb1997 
ABP1 0.05 25feb1998 
ABP1 -0.025 05mar1999 
ABP1 0.06 20mar2000 
ABP1 0.25 05mar2001 
ABP1 0.455 07mar2002 
ABP1 0.73 25feb2003 
ABP1 1.01 19feb2004 
ABP1 1.25 16feb2005 
ABP1 1.65 09feb2006 
ABP1 1.87 08feb2007 
ABT 0.555 14jan1991 
ABT 0.6375 14jan1992 
ABT 0.73 16jan1993 
; 
run; 

/* 5 year moving avg, stdev, cv assuming: 
    one obs per year from 1990 to 2010. 
    observations are already in the sorted order by symbol. */ 
%let START = 1990; 
%let FINISH = 2010; 

data two; 
    array val[%eval(&START-3):&FINISH] val1-val3 val&START-val&FINISH; 
    call missing(of val&START-val&FINISH); 
    do until (last.symbol); 
    set one; 
    by symbol; 
    year = year(date); 
    if &START<=year<=&FINISH then val[year] = value; 
    end; 
    do year = %eval(&START+2) to &FINISH; 
     avg5 = mean(val[year-5],val[year-4],val[year-3],val[year-2],val[year-1]); 
     std5 = std(val[year-5],val[year-4],val[year-3],val[year-2],val[year-1]); 
     cv5 = divide(std5,avg5); 
     if not missing(cv5) then output; 
    end; 
    keep symbol year avg5 std5 cv5; 
run; 

/* check */ 
proc print data=two; 
run; 
/* on lst 
Obs symbol year  avg5  std5  cv5 

    1  ABP1  1999 0.01250 0.05303 4.24264 
    2  ABP1  2001 0.01500 0.04637 3.09121 
    3  ABP1  2002 0.06200 0.11251 1.81461 
    4  ABP1  2003 0.15800 0.19457 1.23146 
    5  ABP1  2004 0.29400 0.30597 1.04071 
    6  ABP1  2005 0.50100 0.37786 0.75422 
    7  ABP1  2006 0.73900 0.40448 0.54734 
    8  ABP1  2007 1.01900 0.46185 0.45324 
    9  ABP1  2008 1.30200 0.46338 0.35590 
10  ABP1  2009 1.44500 0.38726 0.26800 
11  ABP1  2010 1.59000 0.31432 0.19769 
12  ABT  1993 0.59625 0.05834 0.09784 
13  ABT  1994 0.64083 0.08755 0.13662 
14  ABT  1995 0.64083 0.08755 0.13662 
15  ABT  1996 0.64083 0.08755 0.13662 
16  ABT  1997 0.68375 0.06541 0.09566 
*/ 
+0

這workded完美 – John 2010-04-06 07:21:54

3

正確的方法是使用PROC EXPAND。

有很多,你可以用它使用的選項,但你可能想要做

PROC EXPAND DATA=TESTTEST OUT=MOVINGAVERAGE; 
CONVERT VAL=AVG/TRANSFORMOUT=(MOVAVE 5); 
RUN; 

,同樣也MOVSTD。它會自動忽略缺少的值,但您也可以調整該行爲

+0

不夠公平,我不知道PROC EXPAND不包括在BASE SAS。是的,你將需要做一個數據步驟,並將平均數除以標準差。 – 2010-03-19 11:59:57