0

元のデータセットは次のようになります。

sub month y
1   1     1
1   2     2
1   3     3
1   5     5 

私が欲しいのは、各科目の月に基づいて前の 3 ys を取得することです。その月に y が欠落している場合、新しい変数も欠落してい.ます。上記の例では、ラグ 1 はy先月のlag2前、前の y は 2 か月前、lag3これまでは次のようになります。

sub month y lag1 lag2 lag3
1   1     1  .    .    .
1   2     2  1    .    .
1   3     3  2    1    .
1   5     5  .    3    2 

事は私がチェックアウトしlagdif機能することですが、私の場合、私が望むものはlag依存してmonthおり、月の間にギャップもあるため、以前のもののようなlag1機能は使用できません。

また、多くの科目についてもこれを行う必要があります。ありがとう。

4

1 に答える 1

2

SQLソリューション:

data have;
input sub month y;
datalines;
1   1     1
1   2     2
1   3     3
1   5     5 
;;;;
run;

proc sql;
create table want as
    select H.sub,H.month, H.y, One.y as lag1, Two.y as lag2, Three.y as lag3
    from have H
    left join (select * from have) One on H.sub=One.sub and H.month=One.month+1
    left join (select * from have) Two on H.sub=two.sub and H.month=Two.month+2
    left join (select * from have) Three on H.sub=three.sub and H.month=Three.month+3
;
quit;

明らかに、36個必要な場合、これは少し長くなりますが、少なくともそれほど複雑ではありません。これを行うには、他にもさまざまな方法があります。LAGを使用しないでください。これは頭痛の種になり、とにかく適切ではありません。ハッシュの概念に精通している場合は、ハッシュテーブルの方が効率的で、コーディングも少なくて済みます。

ハッシュソリューション:

data want;
if _n_ = 1 then do;
 declare hash h(dataset:'have(rename=y=ly)');
 h.defineKey('sub','month');
 h.defineData('ly');
 h.defineDone();
 call missing(sub,month,ly);
end;
set have;
array lags lag1-lag3;
do prevmonth = month-1 to month-3 by -1;
  if prevmonth le 0 then leave;
  rc=h.find(key:sub,key:prevmonth);
  if rc=0 then lags[month-prevmonth] = ly;
  call missing(ly);
end;
run;

これは、最大36 [または何でも]に拡張するのは非常に簡単です。配列の長さをに変更しarray lags lag1-lag36、doステートメントdo prevmonth=month-1 to month-36 by -1; を実行するだけです。必要な作業のほとんどは、月がここで機能するように配置することです。整数の月を作成するか、月/年などで機能するようにループ基準を変更します。あなたはあなたのデータがどのように指定されているかを示さないので、そこで助けることはできません。

于 2013-02-08T22:11:10.667 に答える