LAG関数の挙動には注意が必要です。
以下のプログラムを実行してみて、予想した結果になるか見てみましょう。
*** サンプルデータ作成 ;
data DT1; do X = 1 to 5; output; end; run;
*** 例1: 2個前の値をとってくる ;
data OUT1;
set DT1;
Y = lag2(X);
run;
*** 例2: IFステートメントを含む場合 ;
data OUT2; set DT1; if X ^= 4 then Y = lag2(X); run;
|
例1は予想通りだと思いますが、例2はどうでしょう?
結果の赤文字で示した部分が「3」になると思ってたら要注意です。
解説
ここから、別記事「
LAG関数の動き」で紹介したイメージをもとに説明するので、この別記事を読んでいないと分かりづらい部分あるかも。
まずは以下、「Y = LAG2(X)」と書いたときの内部処理のイメージです。
(自分なりの解釈になっている可能性があるかもしれませんので、あしからず・・)
まず、LAG関数によって内部で「キュー」と呼ばれる仕組みを利用しています。

続いて、「if X ^= 4 then Y = lag2(X)」というように、IFステートメントと組み合わせたときの内部処理のイメージ。
(こちらも自分なりの解釈になってる可能性あり)

LAG関数が実行されないと、キューの中身が更新されないことによるものですね。
ここでもし、「
IF条件が通った時だけ、2行前の値を取ってきたい」という場合は、以下のようにLAG関数が毎回実行されるように工夫します。
data OUT3; set DT1; Y2 = lag2(X); if X^= 4 then Y = Y2; drop Y2; run;
|
ここからちょっとした裏技を紹介。
上記の処理は、LAG関数とIFN・IFC関数を組み合わせることによって、より簡潔に書くことが出来ます。
data OUT3;
set DT1;
Y = ifn( X^=4, lag2(X), . );
run;
|
解説
IFN・IFC関数の構文は以下の通り。
IFN( 条件式 , 条件がTRUEの場合の戻り値 , 条件がFALSEの場合の戻り値 )
・・・ 戻り値が数値の場合はIFN、文字の場合はIFC関数を使います。 |
そしてこの関数、1つ面白い性質があります。
この関数が実行されるとき、
第1引数の条件式の結果がなんであろうと、第2・第3引数は、内部で両方とも処理(計算)が行われているようです。
つまり今回の 「
ifn( X^=4, lag2(X), . )」 は、
条件式「
X^=4」の結果がTRUEだろうがFALSEだろうが、内部では毎回こっそり第2引数の「
lag2(X)」が実行されています。
毎回LAG関数が実行されることで、2行前の値を取ってくることができているわけです。
この性質、他にも使えそうですね。なんか思いつきそうで思いつかないですが。