マージしたら値が変わってしまう

Last-modified: 2008-09-19 (金) 20:51:54

データセットをマージするステップでは,できるだけ変数加工は避けましょう.マージするついでに変数加工する場合,注意しないと期待した結果にならない時があるからです.
典型的なあやまりの例は,変わるはずのない(と思っていた)変数の値が変わってしまうというケースです.

以下の例は,
売上データ(顧客,商品)に商品単価をつけるため,商品マスタ(商品,単価)をマージしている例です.
単価は1000円単位に変更したいので,マージしながら単価を1000で割っています.しかし,割った結果を元の変数(price)に入れると,続く同じ商品の単価まで,1000円で割られた後の値でマージされ,さらに1000円で割ってしまうという結果になります.

これは,マージ処理が,値のない変数には,前のオブザベーションの変数の値をひきつぐ(retain)させるからで,この処理により,N:1マッチングが実現されています.
この原理をよく理解していない限り,マージのステップ内ではマージによって追加される変数に値を代入すべきではありません.

この例の場合は,1000円単位の変数を別(priceK)に持たせています.
処理時間に問題なければ,マージのステップの後に,あらためて処理するのが安全です.


data tran;
  input custID item $;
cards;
1001 A100
1002 B200
1003 A100
1003 A301
;
data item;
  input item $ price;
cards;
A100 12000
A301 24000
B200 36000
;
proc sort data=tran;by item;run;
proc sort data=item;by item;run;

data tran;
  merge tran(in=in1) item;
  by item;
  /*マージするついでに価格の単位を1000円に直す*/
  *price=price/1000; /* 間違い */
  priceK=price/1000; /* OK */
run;

proc print;run;

/*

  *price=price/1000; /* 間違い */

       cust
OBS     ID     item     price

 1     1001    A100    12.000
 2     1003    A100     0.012 <-間違い
 3     1003    A301    24.000
 4     1002    B200    36.000


  priceK=price/1000; /* OK */

       cust                     price
OBS     ID     item    price      K

 1     1001    A100    12000      12
 2     1003    A100    12000      12 <-OK
 3     1003    A301    24000      24
 4     1002    B200    36000      36
  */