Question

Hye les gars,

J'ai inclus une capture d'écran pour aider à clarifier mon problème:

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

J'essaie de calculer une sorte de moyenne mobile et d'écart type en mouvement. Le truc, c'est que je veux calculer les coefficients de variation (STDEV / AVG) pour la valeur réelle. Normalement, cela se fait en calculant le STDEV et AVG au cours des 5 dernières années. Cependant, il y aura parfois des observations dans ma base de données pour lesquelles je n'ai pas les informations des 5 dernières années (peut-être seulement 3, 2, etc.). C'est pourquoi je veux un code qui calculera l'AVG et le STDEV même s'il n'y a aucune information pour les 5 ans.

De plus, comme vous le voyez dans les observations, j'ai parfois des informations sur plus de 5 ans, lorsque c'est le cas, j'ai besoin d'une sorte de moyenne mobile qui me permet de calculer l'AVG et le STDEV au cours des 5 dernières années. Donc, si une entreprise a des informations pendant 7 ans, j'ai besoin d'une sorte de code qui calculera l'AVG et le STDEV pour, disons, 1997 (d'ici 1991-1996), 1998 (par 1992-1997) et 1999 (1993-1998).

Comme je ne suis pas très familier avec les commandes SAS, il devrait ressembler (très à peu près) comme:

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

Ou quelque chose comme ça, je n'ai vraiment aucune idée, je vais essayer de le comprendre mais ça vaut la peine de le publier si je ne le trouve pas moi-même.

Merci!

Était-ce utile?

La solution

Je préconiserais ProC SQL ici pour la lisibilité. En utilisant les données de Chang Chung comme exemple, vous pouvez essayer ce qui suit:

/* 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;

Autres conseils

La bonne façon de le faire est d'utiliser l'extension proc.

Il y a beaucoup d'options que vous pouvez utiliser avec mais vous voudrez peut-être faire

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

et de même pour movstd. Il ignore automatiquement les valeurs manquantes, mais vous pouvez également ajuster ce comportement

Voici une façon. J'espère que cela t'aides.

/* 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
*/
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top