ラベル 関数: LAG の投稿を表示しています。 すべての投稿を表示
ラベル 関数: LAG の投稿を表示しています。 すべての投稿を表示

2021年5月15日土曜日

LAG関数の動き



LAG関数は「nオブザベーション前の値を取得したい」という場合に役立ちます。

ただし、よくある落とし穴もあるので、最後まで(リンクページも含めて)読んで仕組みを理解したほうが安全です。


簡単な例で見ていきましょう。

*** サンプルデータ作成 ;
data DT1;
input A;
cards;
20
30
10
40
;

data OUT1;
   set DT1;
   B = lag(A);
   C = lag2(A);
   D = lag3(A);
run;

 A 
B
C
D
  20  
  .   
  .   
  .   
  30
  20
  .   
  .   
  10
  30
  20
  .
  40
  10  
  30  
  20  



何が起こっているのか、イメージで説明したいと思います。

(自分なりの解釈になっている可能性があるかもしれませんので、あしからず・・)


今回のサンプルプログラムの「C = LAG2( A )」の時の処理のイメージです。LAG関数によって内部では「キュー」と呼ばれる仕組みを利用しています。


  • 上の例は、ラーメン屋にできた行列みたい。
    • ラーメン屋の行列=「キュー」
    • 行列に並ぶ人=「変数A」
    • ラーメン食べれた人=「変数C」
    • 最初のn杯は店員の味見用に作ったラーメンでお客さんには出さないやつ。
    • 最後に並んだ何名かはスープ切れで食べれなかった、、みたいな

  • 「LAG1」の場合だけ「LAG」と書いてもOK



2015年3月13日金曜日

LAG関数とIFN / IFC関数のコンボ技



LAG関数の挙動には注意が必要です。
以下のプログラムを実行してみて、予想した結果になるか見てみましょう。

*** サンプルデータ作成 ;
data DT1;
   do X = 1 to 5;
      output;
   end;
run;

*** 例1: 2個前の値をとってくる ;
data OUT1;
   set DT1;
   Y = lag2(X);
run;
 X 
Y
  1   
  .    
  2
  . 
  3
  1
  4
   
  5
  3  


*** 例2: IFステートメントを含む場合 ;
data OUT2;
   set DT1;
   if X ^= 4 then Y = lag2(X);
run;
 X 
Y
  1   
  .    
  2
  . 
  3
  1
  4
   
  5
  2 




例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;

 X 
Y
  1   
  .    
  2
  . 
  3
  1
  4
  .  
  5
  3  



ここからちょっとした裏技を紹介。
上記の処理は、LAG関数とIFN・IFC関数を組み合わせることによって、より簡潔に書くことが出来ます。

data OUT3;
   set DT1;
   Y = ifn( X^=4, lag2(X), . );
run;

 X 
Y
  1   
  .    
  2
  . 
  3
  1
  4
  .  
  5
  3  



解説


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行前の値を取ってくることができているわけです。

この性質、他にも使えそうですね。なんか思いつきそうで思いつかないですが。