(ちなみに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の問題など
アイデアがある方はご連絡ください
0 件のコメント:
コメントを投稿