STREAMプロシジャは性質として、内包されるマクロ変数を展開、そして内包されるマクロを実行コードレベルまで展開するけど実行はしないというものを持ってるじゃないですか?
そしてLuaプロシジャは内包するマクロ変数を展開しないという性質がありますよね。
ということはLuaプロシジャでマクロを定義して、それを入れ込んだSTREAMをsubmitする流れをうまく使えば、例えば仕様書的な情報から効率的にプログラム生成できそうじゃないですか?
業界を問わず、仕様書からのプログラム自動生成って割とみんなの夢だと思うんですが、
既存のSASだと、put文で一生懸命作るやり方で、もちろん部分部分をマクロ化して構造的にしていたけども、全体として煩雑なものになりがちだったと思います。
あと地味にSASマクロのクォーティングを気にしてテキスト生成する必要があったりして結構うざい思いをしたことがあると思います。
例えば、以下のデータセットがあって、ここからプログラムを生成するとしたら
data define_table;
titleno='Table-1-1';title='体重の要約統計量';
table='SASHELP.CLASS';target='WEIGHT';method='UNIVARIATE';output;
titleno='Table-2-1';title='性別の頻度集計';
table='SASHELP.CLASS';target='SEX';method='FREQ';output;
run;
以下のように書ける訳です
proc lua;
submit;
--仕様書から情報を抜きつつループ
local dsid = sas.open("define_table")
while sas.next(dsid) do
local titleno=sas.get_value(dsid,"titleno")
local title =sas.get_value(dsid,"title")
local table =sas.get_value(dsid,"table")
local target =sas.get_value(dsid,"target")
local method =sas.get_value(dsid,"method")
--プログラムヘッダー部分
sas.submit
([[
%macro title;
%nrstr(*---------------------------------------) goto newline;
帳票番号 : @titleno@ goto newline;
表名 : @title@ goto newline;
自動生成日: &SYSDATE9 goto newline;
%nrstr(---------------------------------------*)
%mend title;
]])
--プログラム本体部分
local var="VAR"
if method=='FREQ' then
local var="TABLE"
end
sas.submit
([[
%macro main_pg;
PROC @method@ DATA = @table@; goto newline;
@var@ @target@;goto newline;
RUN;
%mend main_pg;
]])
--実際にファイルを生成する部分
sas.submit
([[
filename outf "D:\temp\@titleno@.sas";
proc stream outfile=outf resetdelim="goto";
begin
/%title/
goto newline;
goto newline;
%main_pg
;;;;
]])
end
sas.close(dsid)
endsubmit;
run;
上記を実行すると2つのSASファイルができて、中身は以下のとおりです。
【Table-1-1.sas】
おのおのの部分をつくるマクロを生成しているLuaの部分を関数化などしてやれば
拡張性に富んだ自動生成コードが作れると思うんですよ。
条件分岐とかループも今までのようにマクロで制御するより、Luaで制御し放題なほうが楽だし。
そもそも21世紀にもなって、ずっとputで平テキスト打ってることずっと違和感あったんですよね
医薬業界はもはや言うまでもなくですが、データセットや解析仕様の標準化が進んでいる環境において活かせそうな発想だと思いますけど、どうでしょう?
0 件のコメント:
コメントを投稿