LAG関数を使用したプログラムの注意点

[OS]ALL
[リリース] 6.09e, 6.12, 8.1, 8.2
[キーワード] lag

[質問]

LAG関数をIFステートメントの中で使用している場合、結果が期待と異なる場合があります。なぜでしょうか。

[回答]

この現象は、LAG関数は、キューの操作、つまり値の保存を「実行されたときだけ行なう」という性質を持っているためです。LAG関数は、nオブザベーション前の値を返すのではなく、LAG関数を実行するたびに蓄積されたキューのn個前の値を返します。nオブザベーション前の値を取得するには、LAG関数を毎回実行して全ての値をキューに蓄積する必要があります。
プログラムを例に説明します。下記のプログラムは「前月との気温差をdif、偶数月のときにはその直前の偶数月(その月の2月前)との気温差をdif2」と出力することを目的として作ったプログラムです。

(例1)

  DATA lag ;     INPUT chiku $ month kion ;
     dif = kion - LAG1(kion) ;
     IF  MOD(month,2) = 0 THEN
          dif2 = kion - LAG2(kion) ;
  DATALINES;
  北海道  1 -20
  北海道  2 -18
  北海道  3   0
  北海道  4  10
  北海道  5  20
  北海道  6  15
  北海道  7  20
  北海道  8  28
  北海道  9  22
  北海道 10  17
  北海道 11  10
  北海道 12   2
  ;
  RUN;
(例1で作成されたデータセットlagの内容)
month  kion  dif  dif2  (期待していたdif2の結果)
    1    -20    .     .
    2    -18    2     .  ←  .  = -18 - . 
    3      0   18     .
    4     10   10     .  ←  28 =  10 - (-18)
    5     20   10     .
    6     15   -5    33  ←   5 = 15 - 10
    7     20    5     .
    8     28    8    18  ←  13 = 28 - 15
    9     22   -6     .
   10     17   -5     2  ← -11 = 17 - 28
   11     10   -7     .
   12      2   -8   -26  ← -15  =  2 - 17

上記の結果からわかるように、dif2の結果は2月前のものではなく、「2回前にLAG関数により保存された値との計算結果」となっています。

month  kion dif2  (実際のdif2の計算)
    1    -20    .
    2    -18    .   = -18 - .
    3      0    .
    4     10    .   =  10 - .     (2回前のLAGは存在しない)
    5     20    .
    6     15   33   =  15 - (-18) (2回前のmonth=2で保存された値)
    7     20    .
    8     28   18   =  28 - 10    (2回前のmonth=4で保存された値)
    9     22    .
   10     17    2   =  17 - 15    (2回前のmonth=6で保存された値)
   11     10    .
   12      2   -26  =   2 - 28    (2回前のmonth=8で保存された値)

期待しているとおりの結果を出力させる場合は、次のようなプログラムを実行します。 (例2)

  DATA lag ;
     INPUT chiku $ month kion ;
     dif  = kion - LAG1(kion) ;
     dif2 = kion - LAG2(kion) ;
     IF  MOD(month,2) THEN dif2 = . ; /* 奇数月の場合は欠損値 */
  DATALINES;
  北海道  1 -20
  北海道  2 -18
  北海道  3   0
  北海道  4  10
  北海道  5  20
  北海道  6  15
  北海道  7  20
  北海道  8  28
  北海道  9  22
  北海道 10  17
  北海道 11  10
  北海道 12   2
  ;
  RUN;
(例2で作成されたデータセットlagの内容)
month  kion  dif  dif2
    1    -20    .     .
    2    -18    2     .
    3      0   18     .
    4     10   10    28
    5     20   10     .
    6     15   -5     5
    7     20    5     .
    8     28    8    13
    9     22   -6     .
   10     17   -5   -11
   11     10   -7     .
   12      2   -8   -15