最近いただいた意見で
「Luaをマクロの代わりにできるというイメージがわきません。
例えば、患者背景の一覧表作成に際して,数値データに対して要約統計量をだし、文字データに対しては頻度集計を行うといったマクロを最初にそれぞれ作って、適宜実行し、結果を成型して結合していますが、同じことがLuaでもできますか?」
というのがありました。
どっちでやるのがいいのかという議論はさておき、当然可能です。
細部まで作りこむのが面倒だったので、ざっくりこんな感じかなっていうのを作ってみました。
最初にマクロを定義して、適宜実行ということなので、プログラムの途中途中で呼び出すのだと思いますから、パラメータマクロと同じ機能を、Luaの関数でグローバルにして定義しています。
プログラムごとに管理するなら最初のproc luaにrestartをつけて、そこで一度リセットするようにしておけばよいでしょう。
/*Luaでパラメターマクロっぽく関数を定義*/
proc lua restart;
submit;
--カテゴリデータに対して頻度集計する関数
function freq(ds,var)
local code = [[proc freq noprint
data=@ds@;
tables @var@/out=temp
(rename=(@var@=out2 count=out3));
quit;
data out_@var@;
set temp;
out1="@var@";
run;
]]
sas.submit(code)
end
--数値データに対して要約統計量をだす関数
function summary(ds,var)
local code = [[proc summary noprint
data=@ds@;
var @var@;
output out=temp(drop=_TYPE_ _FREQ_)
mean=Mean std=Std min=Min median=Median max=Max;
quit;
proc transpose data=temp out=out_@var@;
run;
data out_@var@;
set out_@var@;
out1="@var@";
out2=_NAME_;
out3=col1;
run;
]]
sas.submit(code)
end
endsubmit;
quit;
で、あとは実際使用する場所で、いかのようにパラメータを指定して実行します
マクロを実行するようにluaの関数を実行する
proc lua;
submit;
freq("sashelp.class","sex")
summary("sashelp.class","age")
summary("sashelp.class","height")
summary("sashelp.class","weight")
endsubmit;
quit;
/*ただのデータステップで結果を結合すれば*/
data output;
length out1 out2 $50.;
set out_:;
keep out:;
run;
round入れるべきでしたが、まあこんなもんでしょう。
データセットを指定したら、全変数に対して自動で数値型ならsummary 文字ならfreqをかけて
結果の結合までやる関数が欲しければ、以下のようにすればいいでしょう
proc lua;
submit;
function autoreport(ds)
local dsid = sas.open(ds)
for var in sas.vars(dsid) do
if var.type == "C" then
freq(ds,var.name)
end
if var.type == "N" then
summary(ds,var.name)
end
end
sas.close(dsid)
sas.submit([[
data auto_output;
length out1 out2 $50.;
set out_:;
keep out:;
run;
]])
end
endsubmit;
run;
proc lua;
submit;
autoreport("class")
endsubmit;
run;
結果は上とだいたい同じですが、NAMEもカテゴリ集計されちゃうので、そういう部分の処理の工夫は必要ですね。
どうでしょう?作ってる感じとしてはマクロ作るのと、感覚的に大差ないので、スムーズに移行できると思いますが。
0 件のコメント:
コメントを投稿