書くのは恥だが役に…って類いのコード
例えば、以下のような3つのデータセットがあって
data A;
ID=1;SEX="M";GRP=1;output;
ID=2;SEX="F";GRP=1;output;
ID=3;SEX="M";GRP=3;output;
ID=4;SEX="F";GRP=2;output;
ID=5;SEX="F";GRP=2;output;
run;
data B;
ID=1;SEX="M";WEIGHT=75;output;
ID=2;SEX="F";WEIGHT=55;output;
ID=3;SEX="M";WEIGHT=65;output;
ID=4;SEX="F";WEIGHT=45;output;
ID=5;SEX="F";WEIGHT=85;output;
run;
data C;
GRP=1;HEIGHT=175;output;
GRP=1;HEIGHT=155;output;
GRP=1;HEIGHT=165;output;
GRP=2;HEIGHT=145;output;
GRP=2;HEIGHT=185;output;
run;
BでSEXごとに求めた要約統計量をSEXをキーにしてAに結合、
CでGRPごとに求めた要約統計量をGRPをキーにしてAに結合っていうような
処理を埋め込み系のマクロにして、1ステップ中にいくらでも入れれるようにしたいなと思いました。
ようするにこういうこと
data D;
set A;
%get_summary(dataset=B,key=SEX,var=WEIGHT)
%get_summary(dataset=C,key=GRP,var=HEIGHT)
run;
結果は(画像は途中まで)
で、肝心のマクロの中身は
%macro get_summary(dataset=,key=,var=);
%let qkey = %sysfunc( tranwrd( %str("&key") , %str( ) , %str(",") ) );
length &var &var._SUM &var._MEAN &var._StdDev &var._MIN &var._MAX 8.;
call missing(of &var &var._SUM &var._MEAN &var._StdDev &var._MIN &var._MAX );
if _N_=1 then do;
rc=dosubl("proc summary data=&dataset nway;class &key;var &var.;
output out=temp sum= mean= std= min= max=/autoname");
declare hash h&sysindex.(dataset:"temp");
h&sysindex..definekey(&qkey);
h&sysindex..definedata("&var._SUM","&var._MEAN","&var._StdDev","&var._MIN"
,"&var._MAX ");
h&sysindex..definedone();
rc=dosubl("proc delete data=temp;run;");
end;
if h&sysindex..find() ne 0 then call missing(of &var._SUM &var._MEAN &var._StdDev &var._MIN &var._MAX);
drop rc &var. ;
%mend get_summary;
けど、まあ、当然に感じる人が大半かもしれないけど、ハッシュに格納する直前で、このタイミングでデータセット作って間に合うっていう感覚は個人的には斬新。
dosubl関数は、call executeと違って、データステップの途中で即時的に処理が開始できる特性があります。
なのでdosubl関数でデータセット作って、そのままハッシュに入れて、すぐ消してるんですね。小賢しい…
だから見かけ上は1ステップでも、速くはないです(mergeよりかは速いけど)。
あらかじめプロシージャ回してデータセット作ってからハッシュに格納するのと同じです。
本来これはDS2でやるか、ハッシュ内でループで計算してから繋ぐ書き方でやる処理なんですね…。
ちなみに、思いつきでパパッと書いたマクロなんで、使うならちゃんと検証してくださいね。
多分、穴はあると思います。まず、再帰ができない、ようするにset対象自身を指定できないとかね。
あと複数変数指定にも対応してないですね
あ、今書いてて思ったんですけど、この記事、SAS忘備録の
「データステップ内でプロシジャを実行する。」の焼き増しですね。
http://sas-boubi.blogspot.jp/2016/05/blog-post_17.html
0 件のコメント:
コメントを投稿