BYグループごとにある変数が最大の値を持つレコードのみ残す、ただし同値で複数存在する場合は複数レコードを残す処理_RANKプロシジャは使える子という話

ある変数が最大のオブザベーションのみ残す処理と聞くと、まず思いつくのはソートして、LAST.でオブザベーションを残す方法かなと思います。

ただし、次のようなケースならどうでしょうか。

いま、以下のデータセットがあるとします。

data Q1;
X=1;Y=1;Z='い';output;
X=1;Y=2;Z='ろ';output;
X=1;Y=3;Z='は';output;
X=1;Y=3;Z='に';output;
X=2;Y=3;Z='い';output;
X=2;Y=4;Z='ろ';output;
X=3;Y=.;Z='い';output;
X=4;Y=5;Z='い';output;
X=4;Y=5;Z='ろ';output;
X=4;Y=5;Z='は';output;
run;
proc sort data=Q1;
 by X;
run;














このデータセットで、例えばXでグループ化して、その中で最大のYを持つオブザベーションを残す
とします。例えばX=2のグループであれば、Y=4のオブザベーションだけ残したいわけです。
ただし、X=1のグループではY=3が最大なのですが、Y=3のオブザベーションは2つあります。
その場合は2オブザベーション残したいとします。

その場合の処理を考えてみます。

まあ、まずはXの値ごとのYの最大値をmeansだのunivariateなんだので出して、それと元データをマージしてくっついたやつだけ残すとか、SQLでサブクエリにすればいいとか、まあ色々方法はあると思いますが、

こういったケースで個人的に一番いけてると思っているのはrankプロシジャです。

proc rank data=Q1 out=A1(where=(RANK in (.,1))) ties=low descending;
var Y;
ranks RANK;
by X;
run;

これで結果は










はい詰んだ!

もし欠損値を認めない場合は(where=(RANK =1))としてください。

ranksステートメントをつけないと、Yの中身が順位番号データに上書きされるから要注意!
ties=lowは同じ値がたくさんあった時に、順位が一番小さくなる値を採用するというもので
同着1位が三人いたら、三人とも一等賞という指定です、ここをhighにすると
同着1位が三人いたら、三人とも三等賞という指定です。
他には例えば、平均にもできますし、他のオプションと組み合わせると色々面白いので
ヘルプみてください

descendingは降順に順につけてます。


RANKSプロシジャって結構色々応用できて、楽しいですよ。
古くからあるのに使えねぇプロシジャだと言った人は猛省してください。













0 件のコメント:

コメントを投稿