2014年9月17日水曜日

変数値をマクロ変数に格納する方法「CALL SYMPUTX編」




SASを覚えはじめたという方から、この質問を頂くことが多いので解説したいと思います。
(最後に注意点の記事リンクも貼ったので、そちらも要参照)


* サンプルデータ ;
data DT1;
input A$ B$ @@;
cards;
001 AA 002 BB 003 CC
;

 
B
 001
 AA
 002
 BB 
 003
 CC 



上記の変数A,Bの値をマクロ変数に格納してみましょう。

* 変数値をマクロ変数に格納 ;
data _null_;
    set  DT1  end=_EOF;
    if  _EOF then call symputx("OBS", _N_);
    call symputx( cats("A",_N_) , A );
    call symputx( cats("B",_N_) , B );
run;

* ログにマクロ変数値を展開 ;
%macro MAC;
    %do i=1 %to &OBS;
         %put  &&A&i  &&B&i;
    %end;
%mend;
%MAC;

ログ
001  AA
002  BB
003  CC


上記青字部分の解説

end = 一時変数名 
最後のオブザベーションを読み込んだ時、一時変数に「1」が入る。
一時変数名は任意の名前でOK
call symputx
構文・・・call symputx("マクロ変数名", 格納したい値 )
値をマクロ変数に格納する。
_N_
SASの自動変数で、データステップの反復回数が格納されている。
つまり、読み込んだオブザベーションに対して、1~連番をふったような値が入る。
cats関数
構文・・・cats(値1値2 … )
値の両端の半角スペースを取り除いて結合する。
%doループ
%do マクロ変数名 = 開始値  %to 終了値;
%end;
マクロ変数の値を開始値から終了値まで変化させながら、ループさせる。


処理の流れ

data _null_;
    set  DT1  end=_EOF;
    if  _EOF then call symputx("OBS", _N_);
最後のオブザベーションを読み込んだ時に、_N_の値をマクロ変数OBSに格納している。
(つまりオブザベーション数をマクロ変数に格納)

    call symputx( cats("A",_N_) , A );
    call symputx( cats("B",_N_) , B );
run;
変数Aについて
1オブザベーション目の値をマクロ変数A1に
2オブザベーション目の値をマクロ変数A2に
・・・と次々マクロ変数に格納していく。変数Bも同様。

%macro MAC;
    %do i=1 %to &OBS;
         %put  &&A&i  &&B&i;
    %end;
%mend;
%MAC;
%DOでマクロ変数 i の値を1,2,3…と変化させながら、オブザベーションの数だけループさせる。
%PUTを使って、マクロ変数A1,B1,  A2,B2, ・・・の値をログに展開していく。



📝注意点

「CALL SYMPUTX」で数値をマクロ変数に格納すると丸められる場合があるので注意
今回のテクニックの中で使用している「_N_」と「END=オプション」は「サブセット化IF」と一緒に使用すると正しく動かなくなる事があります。
(解説記事:「サブセット化IFでありがちな落とし穴」)


次回はSQLプロシジャを使った方法を紹介。


0 件のコメント:

コメントを投稿