SAS

Proc sqlを極める(2) ーdistinctキーワード、統計量の算出ー

proc sqlの第2回目です。distinctキーワードと統計量の算出はどちらもデータステップとmeansプロシジャで代用可能ですが、可読性の高さと複数の処理を同時に実施できるため
もっともおすすめな利用方法です。

distinctキーワード

distinctキーワードは指定して変数の値から重複を削除にユニークにする命令です。
sasプロシジャでいうとproc sortのnodupオプションと同等の処理を実現します。

指定した変数から重複削除する

select 
   distinct origin, 
   make 
from sashelp.cars;

上記のコードは変数originとmakeの組み合わせから重複を削除します。

なおすべてのカラムの組み合わせから重複を削除するには 「distinct *」とします。

proc sortとの違い

SQLはdistinctキーワードによりproc sortのnodupオプションと同じ処理が実行できますが、nodupkeyオプションと同様の処理を行うためには
工夫が必要となります。

data test; 
input usubjid $ lbcat aval; 
cards; 
a01 1 1.1 
a01 2 1.4 
a01 3 24.1 
a01 4 2000 
b01 1 3.0 
b01 2 1.2 
b01 3 50 
b01 4 1800 
c02 1 3.2 
c02 2 0.5 
; 
run; 
proc sort data=test nodupkey out=out1; 
by usubjid;run;

上記のコードを実行すると、各usubjid毎にlbcat=1のレコードが出力されます。

proc sortでbyステートメントで指定した変数をキーとして重複削除するとき、
重複があるレコードのうち最初に現れるレコードのみを保持し、残りを削除する仕様となっています。
この仕様を利用してデータセットを作成されている方も多いでしょう。

それに対しproc sqlではnodupkeyオプションと同等のキーワードは存在しないため、あらかじめデータを前処理するなどして対応する必要があります。

上記のデータセットはusubjid, lbcatで昇順に並んでいるため、proc sortで重複削除した場合出力されるのは
usubjid毎にlbcatが最も小さいレコードとなります。したがって同等の結果を出力するsqlは以下のようになります。

select * 
from test 
group by usubjid 
having lbcat=min(lbcat);

proc sortと異なり事前にソートする必要はありません。そのためsqlを使ったほうがプログラムの記述が若干少なくなります。

統計量の算出

「要約関数(変数名) as 統計量を格納する変数名」とすることで、指定した変数の統計量を算出できます。
この時group by句を併用することで群変数ごとに統計量を算出できます。

data test; 
input usubjid $ lbcat aval; 
cards; 
a01 1 1.1 
a01 2 1.4 
a01 3 24.1 
a01 4 2000 
b01 1 3.0 
b01 2 1.2 
b01 3 50 
b01 4 1800 
c02 1 3.2 
c02 2 0.5 ; 
run; 

proc sql; 
select 
   lbcat, 
   count(aval) as n, 
   min(aval) as min, 
   max(aval) as max, 
   mean(aval) as mean, 
   std(aval) as std, 
   median(aval) as median 
from test 
group by lbcat; 
quit;

上記のコードはlbcatごとにavalの要約統計量を出力し、新規変数へ格納しています。

同等の処理はproc meansなどでもできますが、SQLのほうが出力データセットの構造を定義しやすく、わかりやすいコードになります。
proc meansはoutputステートメントの記述がちょっと独特ですよね・・・

基本的な要約統計量の算出についてはproc sqlとproc meansの両者は同等の機能を有しますが、丸め誤差が発生する点は注意が必要です。
ダブルプログラミングでコンペアを実行するときは値を丸める必要があります。

被験者数をカウントする

もっとも汎用性の高い使い方は被験者数をカウントするときでしょう。

SASプロシジャを使って上記のデータから被験者数をカウントする方法はいくつかありますが、あらかじめproc sortで
重複を削除して集計用変数を追加した後、proc freqでカウントする方法が教科書的でしょうか。

data test2; 
set test; cnt=1; 
proc sort nodupkey; 
by usubjid; 
run; 

proc freq data=test2 noprint; 
tables cnt / out=out1; 
run;

これをproc sqlで実施するとこうなります。SASプロシジャよりもずっとシンプルな表記となります。

proc sql noprint; 
create table out2 as 
select 
   count(distinct usubjid) as cnt 
from test; 
quit;

被験者数をカウントする処理は頻出なのでSQLで実施する方法は知って損はないかと思います。