2014年5月20日火曜日

行削除の落とし穴




行(オブザベーション)を削除する方法はいくつかありますが、その方法によっては注意が必要です。



サンプルデータ
data DT1 DT2 DT3;
   do A=10 to 30 by 10;
       output;
   end;
run;

データセットDT1~DT3

 A 
  1  10 
  2  20 
  3  30 



まずは色々な方法で行を削除してみる。
* ①DELETEステートメント ;
data DT1;
   set DT1;
   if A=10 then delete;
run;

* ②MODIFY,REMOVEステートメント ;
data DT2;
   modify DT2;
   if A=10 then remove;
run;

* ③SQLのDELETE句 ;
proc sql;
   delete from DT3 where A=10;
quit;


データセット
DT1

 A 
  1 20 
  2 30
DT2

 A 
  2 20 
  3 30
DT3

 A 
  2 20 
  3 30


出来たデータセットを開いてみると上記のような感じです。いっけん同じに見えるけど、注目してほしいのはデータセットの左側に表示される行番号。
DT2とDT3は「2」から始まってますね。

1行目が削除されても行番号が削除前と変わっていないのです。
このように使用できる行番号が歯抜け状態になってしまうことでちょっとした問題を起こす場合があります。




問題を起こすケース


行削除後の行数取得。
data _null_;
   set DT2 nobs=NOBS;
   put "行数= " NOBS;
   stop;
run;

ログ
行数= 3

NOBS=を使って行数を取得しログに出力しています。
本来は「行数= 2」となるはずですよね。


POINT=を使った行の読み込み。
data DT4;
   do X=1 to NOBS;
      set DT2 nobs=NOBS point=X;
      output;
   end;
   stop;
run;

データセットDT4

 A 
  1 . 
  2 20 
  3 30 

POINT=で読み込む行番号を変数Xの値によって指定してます。
結果を見ると、1行目が欠測値になってズレちゃってますね。



対策

もしSQLのDELETE句やREMOVEステートメントで行を削除してたら、、、以下のようにSETし直せばOK。

data DT2;
   set DT2;
run;


data _null_;
   set DT2 nobs=NOBS;
   put "行数= " NOBS;
   stop;
run;

ログ
行数= 2



0 件のコメント:

コメントを投稿