3

やあみんな、

問題を明確にするためにスクリーンショットを含めました。

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

ある種の移動平均と移動標準偏差を計算しようとしています。実際の値の変動係数(stdev / avg)を計算したいのです。通常、これは過去5年間の標準偏差と平均を計算することによって行われます。ただし、データベースに過去5年間の情報がない観測値が存在する場合があります(たぶん3、2など)。そのため、5年間の情報がない場合でも、avgとstdevを計算するコードが必要です。

また、観測でわかるように、5年以上の情報を持っていることがあります。その場合、過去5年間の平均と標準偏差を計算できるような移動平均が必要です。したがって、企業が7年間の情報を持っている場合、たとえば1997(1991-1996まで)、1998(1992-1997まで)、1999(1993-1998)の平均と標準偏差を計算するある種のコードが必要です。

私は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))

または、このようなもの、私は本当に手がかりがありません、私はそれを理解しようとするつもりですが、私がそれを自分で見つけられないのであれば、それを投稿する価値があります。

ありがとう!

4

3 に答える 3

3

それを行う正しい方法は、PROCEXPANDを使用することです。

あなたがそれで使うことができる多くのオプションがあります、しかしあなたはしたいかもしれません

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

同様にMOVSTDの場合。欠落している値は自動的に無視されますが、その動作も調整できます

于 2010-03-18T02:50:53.900 に答える
1

これが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
*/
于 2010-03-17T14:44:45.510 に答える
0

読みやすくするために、ここでprocsqlを推奨します。Chang Chungのデータを例として使用すると、次のことを試すことができます。

/* 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;
于 2010-03-23T08:09:42.157 に答える