IFステートメントにおけるLAG関数の挙動の話

明けましておめでとうございます。今年もよろしくお願いします。

さて、以前IFステートメントでlag関数を使うときは注意が必要といったことを書いたような気がしますが、具体的にどういうことなのかを書きます。

実はSASのHPに同じことが書いているんですが、、申し訳ないけど、
いや、はっきり言ってわかりにくい!
http://www.sas.com/offices/asiapacific/japan/service/technical/faq/list/body/ba096.html


例えば以下のようなデータセットがあったとします。

data Q1;
X=1;output;
X=3;output;
X=2;output;
X=4;output;
X=5;output;
X=0;output;
X=6;output;
run;













今、やりたい処理が

「Xの値が3未満の場合、ひとつ前のXの値をYという変数に入れる」
という処理の場合、

data A1;
 set Q1;
 if X<3 then Y=lag(X);
run;

と書いてしまいそうなのですが、結果は












見当違いの悪手失着です。
あれ?一つ前だから、3obsは3,6obsは5じゃないの??といった感じですが、
実は上記のコードで実現されたのは
「Xの値が3未満の場合、ひとつ前にXが3未満であったときの値をYという変数に入れる」

という処理です。つまりIF条件式を通過したobsをカウントして、lagなら1つ前、lag2なら2つ前というように考えるのです。


挙動さえ理解していれば、条件に合致した前の値をとるといった処理が書きたい時に

data A0;
 set Q1;
 retain Y_;
 if X<3 then do;
  Y=Y_;
  Y_=X;
 end;
 drop Y_;
run;

のように第一感で浮かぶretainステートメントを使う必要もなく、コードがコンパクトになります。


ちなみに、最初に書いた「Xの値が3未満の場合、ひとつ前のXの値をYという変数に入れる」
をやりたい場合は

data A1;
 set Q1;
 Y_=lag(X);
 if X<3 then Y=Y_;
 drop Y_;
run;




のように、一度単純にlag関数を使って値を割り当ててから、IFします。








0 件のコメント:

コメントを投稿