以前、meansまたはsummaryプロシジャのclassdata=オプションは集計表を作成するうえで役立つと言い詳細はまた紹介すると書きました。
(ちなみにmeansとsummaryの違いは、デフォルトでアウトプット出力するかどうかです。つまりmeansにnoprintをつければsummaryと同じで、逆にsummaryにprintをつければmeansと同じです。)
またtransposeプロシジャのIDステートメント複数づけのおかげで、集計表が作りやすくなったとも言い、実例をいつか紹介すると書きました。
遅くなりましたが、ざっくりとした流れを紹介したいと思います。
今、以下のようなデータセットがあるとします
data Q_1;
GROUP='A';SUBGROUP='X';LEVEL1=2;LEVEL2=1;LEVEL3=5;output;
GROUP='A';SUBGROUP='Z';LEVEL1=1;LEVEL2=0;LEVEL3=4;output;
GROUP='B';SUBGROUP='Z';LEVEL1=1;LEVEL2=0;LEVEL3=3;output;
run;
で、GROUPはA群とB群がいて
それぞれのグループにSUBGROUP X、Y、 Zがあるとします。
そして、3つの変数があり
LEVEL1は1-2の値をとります。
LEVEL2は0-1の値をとります。
LEVEL3は3-5の値をとります。
ところが、今まだデータが集まっていない、またはデータの収集が打ち切られた等の
理由で、たった3オブザベーションしかありません。
このわずかのデータで
のようなEXCELの集計表テンプレートに出力する必要があるとします。
つまり、大半のセルは0になります。
どんな言語でも、あるデータをだすのは簡単ですが、ないデータをだすプログラムは難しいものです。とりあえず先にコード全部のせます。
data CLDS;
do GROUP='A','B';
do SUBGROUP='X','Y','Z';
do DUMMY=0 to 20;
output;
end;
end;
end;
run;
/*================================================
マクロ名:syogi
引数-①dsname 対象データセット
②varname 対象変数
③minval 対象変数のとりうる最小のカテゴリ数値
④maxval 対象変数のとりうる最大のカテゴリ数値
=================================================*/
%macro syougi(dsname,varname,minval,maxval);
proc means data=&dsname.
classdata=CLDS(rename=(DUMMY=&varname.) where=(&minval.<=&varname.<=&maxval.))
noprint nway exclusive;
class GROUP SUBGROUP &varname.;
var &varname.;
output out=&varname._(drop=_TYPE_ _FREQ_) N=COUNT;
run;
proc sort;
by &varname.;
run;
proc transpose data=&varname._ out=_&varname.(drop=_NAME_ rename=(&varname.=VAL)) delimiter=_;
var COUNT;
id GROUP SUBGROUP;
by &varname.;
run;
%mend;
/*実行*/
%syougi(Q_1,LEVEL1,1,3)
%syougi(Q_1,LEVEL2,0,1)
%syougi(Q_1,LEVEL3,3,5)
data A_1;
set _:;
run;
/*EXCEL出力*/
libname OUTEX "D:\集計.xlsx" header=no scan_text=no;
data OUTEX."Sheet1$D11:I18"n ;
set A_1;
modify OUTEX."Sheet1$D11:I18"n ;
F1=compress(put(A_X,best.));
F2=compress(put(A_Y,best.));
F3=compress(put(A_Z,best.));
F4=compress(put(B_X,best.));
F5=compress(put(B_Y,best.));
F6=compress(put(B_Z,best.));
run;
libname OUTEX clear;
まず、CLDSというのを作っています。
これはクラスデータセットといって、meansのクラスで指定する変数の、フルパターンをクラスデータセットに作成しておくことで、カウントであれば実際のデータの水準が足りなくても0で補完して計算してくれます。
ただ、1つの変数に対しての集計ならいいのですが、複数で、かつ採りうる値が変数ごとに違う場合、変数分それに対応するクラスデータセットをつくってたら煩雑すぎます。
なので、通常、群やサブグループなど固定のクラス変数は固定して、それ以外のカテゴリ値の部分は一端ダミーの変数名にして、大きめにデータセットを作っておきます。
以下がCLDSの中身(一部です)です。
(一部です)
それで、マクロの中で、実際に集計する対象の変数を指定して、ダミー変数をその変数名にrenameして、かつそのカテゴリ値の採りうる値でwhereでクラスデータセットを絞っています。
以下が、マクロにLEVEL1を指定した時の、meansからoutされたデータセットです。
欠損水準を0で補って、フルセットで集計されています。
しかしこのままだと縦持ちなのでこれをグループ、サブグループで転置します。
以下は上記のデータセットがtransposeされた後のデータセットです
delimiter=でアンダーバーを追加しています。
たとえば、A_XはグループAのサブグループXの集計結果というわけです。
それでLEVEL1-3までを集計してその結果をコロンモディファイア指定でSetしてつなぎます。
最後にLIBNAME EXCELでだしていますが、DDEでもなんでもいいです。
ざっくりとした例なので、実際に使用される場合は、適宜書き換えてください(とりあえずマクロ名変えましょう)。そのままべたっと貼っても動きません多分。
で注目点はクラスデータと、実際のデータのフォーマットやラベルなどのメタデータが同期していることが必要なのでLENGTHを合わせたり、
proc datasets nolist;
modify Q_1;
attrib _all_ informat= format= label='';
quit;
などで、余計なメタデータを消しておいた方がいいです。
classdata=使うといつもエラーになって、あきらめますという話を聞くのですが
大半はここが原因です。
あと最後に、若干ネタ切れ感がでてきたので、取り上げてほしい部分や、詰めSASの問題など
アイデアがある方はご連絡ください