全てがnullであった時を問題とするブランクチェックについて、データ構造が縦型と横型であった場合の違い

生データをチェック・クリーニングする際に、ブランクチェックは頻度の高い処理です。

たとえば今A,B,Cという変数があって、どれか1つ以上でも値が入っていれば、問題なし。
全てが欠損値であるデータをピックアップしたいという状況があったとします。

例えばデータが

data Q1;
IDNO='001';A=.;B=.;C=10;output;
IDNO='002';A=.;B=.;C=.;output;
IDNO='003';A=5;B=.;C=.;output;
run;







こんな感じならwhereで単純に=.をandでつないでもいいし

data A1;
 set Q1;
 if coalesce(A,B,C)=.;
run;

こんな感じでもいいし、簡単です。





少し頭を使うのは、同じ意味であってもデータ構造が

data Q2;
IDNO='001';ITEM='A';VAL=.;output;
IDNO='001';ITEM='B';VAL=.;output;
IDNO='001';ITEM='C';VAL=10;output;
IDNO='002';ITEM='A';VAL=.;output;
IDNO='002';ITEM='B';VAL=.;output;
IDNO='002';ITEM='C';VAL=.;output;
IDNO='003';ITEM='A';VAL=5;output;
IDNO='003';ITEM='B';VAL=.;output;
IDNO='003';ITEM='C';VAL=.;output;
run;











こういう場合です。
1つのIDにつき項目ごとにオブザベーションが別れています。
問題にすべきはA,B,C全てが欠損である002のIDで、それを特定したいわけですが、
さて、どう書きましょうか?

まず1つとしては

proc transpose data=Q2 out=Q2_(drop=_NAME_);
 var VAL;
 by IDNO;
 id ITEM;
run;

とすれば、最初の問題のデータ構造に転置されるので、そうしてから
同じやり方で片付ける方法です。

縦に解く問題が難しければ、横にすればいいし
横に解く問題が難しければ、縦にすればいいというのはSASの定跡ですね。

まあ、でもこの場合、わざわざデータ構造を変えなくても
例えば、

proc means data=Q2 nway noprint;
class IDNO;
var VAL;
output out=A2(where=(S=.)) sum=S;
run;





このようにすれば、IDごとにAからCの合計をだしてくれるわけですが
sumによる加算結果がnullになるのはどんな時でしょうか?
それは対象全てがnullであったときのみです。その他の場合はnullを除いて足し算してくれます。
すなわちsumがnullであればA,B.Cすべてnullであることに他ならないので
上記のコードでID 002を特定できるわけです。
maxとかでももちろんいいです。


他のアプローチとして、

proc sort data=Q2;
 by IDNO VAL;
run;

data A3;
 set Q2;
 by IDNO VAL;
 if last.IDNO and VAL=.;
run;





もアリですね。

ID順、VAL順にソートして、各IDの最後のVALがnullである場合は、そこまでの全てのVALがnullであることと同義ですからね。









0 件のコメント:

コメントを投稿