指定した変数を除いて、それ以外の全ての変数を関数の対象にするマクロ


少し早いですが、PC内のファイルの年末大掃除をしていた際に
まだSASを覚えてそんなにたっていない頃に作ったマクロがでてきて、

僕自身、存在すら完全に忘れてたのですが
これが結構面白い発想のものだったので、自画自賛ながら紹介します。

例えば以下のように変数の多い、横長なデータセットがあった場合を考えます

data Q1;
A=1;B=2;C=5;D='あ';E=8;F=4;G='い';H='A';I=9;output;
A=4;B=3;C=2;D='い';E=6;F=2;G='ろ';H='A';I=5;output;
run;






AとBの合計を出してとかだったら sum(A,B)で余裕ですし、
AとB以外の合計を出してと言われたらsum(of C-numeric-I);でいけますよね。
(※変数名--変数名は変数の格納位置を指定する方法です。
間にnumericやcharacterを挟むことで、数値型か文字型で絞れます)

でも、きっついのが、変数の格納順が定まってなかったり、横に変数が増えていくような
ことが想定される、つまりケツにくる変数名が不明、特定できない場合に
sum(of C-numeric-I);の方法は使えません。

さらに痛いのがEとI以外の合計を出してみたいなケースで、
sum(A,B,C,F);みたいに全部列記して書くか、、それでも変数が可変的に追加される状況では
決め打ち対応できません。

そういった時に昔の僕が捻くり出したのが以下のマクロです。

%macro noarray(INDS,OUTDS,EXLIST,FUNC);
 data &OUTDS;
 informat &EXLIST DUMMYST;
 set &INDS;
  DUMMYST=.;
  DUMMYEND=.;
  RESULT=&FUNC(of DUMMYST-numeric-DUMMYEND);
  drop DUMMYST DUMMYEND;
 run;
%mend noarray;

INDSに流し込むデータセット名
OUTDSに作成するデータセット名
EXLISTに関数の対象から除外する変数リスト
FUNCにはSUMやMEANやMAXなど数値対象の関数を指定します。

=======================
以下、実行例
=======================
%noarray(Q1,A1,A B,sum)
これはAとB以外をsumしています 結果は




%noarray(Q1,A2,E I,sum)
これはEとI以外をsumしています 結果は




%noarray(Q1,A3,C I D,mean) 
これはCとIとD以外をmeanしています 結果は





なかなか面白いのが、関数の指定に変数順を使用して、
対象除外の変数を一番先頭にして、その後ダミーのスタート地点と
ダミーのゴールとなる変数を定義しているところですね。

numericのところを消せば、文字数値共通で引数にとれる関数に使えますし
characterにすれば文字型変数版マクロに早変わりですね。
てか、ここ自体、マクロパラメータにしちゃえばいいですね。

で、思い出深いのが、noarrayというマクロ名です。
array、配列がどうしてもわからなくて、使うのが凄い苦手だったんです。
で、マクロも苦手だったので、変数名をマクロにいれるとか、配列をつかうとかいう発想が
でなかったんです。それでこういう名前にしたんですね。





6 件のコメント:

  1. これは素晴らしいアイディアですね。
    この要らない変数を先頭に追い出すテクニック、実戦で使用させてもらいます!

    それと何回かブログとか記事を紹介してくれてありがとうございます。
    こちらも詰めSASの記事リンク貼ったり、引用することがあると思いますが、よろしくお願いします。

    返信削除
  2. 有難うございます!
    僕にしては珍しくクリエイティブなアイデアでした。
    つかっていただけたら、もう気分最高です。

    もう既に把握されていると思うのですが念のため、欠損でダミー変数つくっているんで
    sumとかmeanとか欠損値の変数を除外する系の関数なら問題ないですが
    cmissの話ではないですが、欠損値の変数も対象に含める関数使う場合はご注意ください。

    なんかもっといい方法ないもんですかね、変数を指定して、それを除外して配列に指定するみたいな書き方とか。

    記事、勝手に紹介しててすみませんでした!そして有難うございます!
    自由に引用でもなんでもしていただけると嬉しいです。悪い例としてバンバン吊るしあげてください!

    返信削除
  3. いつも参考にさせて頂いています。
    今回のMacroは汎用性もあり、とても参考になりました。
    今後も更新を楽しみしています!

    返信削除
    返信
    1. ひょうどうさん、コメント有難うございます。そういっていただけると嬉しいです!
      いつも趣味の垂れ流し的内容ですが、たまには有用な情報もだせるように頑張ります。僕は、最初、医薬系の人に多く見ていただいていると思いこんでいたのですが、いただいたメッセージ等から、そんなことなくて色んな分野の方に見ていただいていることを知りました。おかげで世界が広くなりました。
      もし、もっとこういった内容が知りたいとか、こういう機能のマクロ作ったことないかとかがありましたら自由にメッセージでもコメントでもください。

      削除
    2. SAS YAMAさん、マーケティングの分野でのあったら便利なマクロ機能など、いろいろ今後ご連絡させて頂ければと思います。私が取り組んでいる現在のプロジェクトでは、通常はエクセルからインポートすることが多かったデータをGoogleのスプレッドシートにSASからアクセスしてインポートを行うようことでデータのアップデートを簡素化できるようにシフトしています。

      削除
    3. なんか、凄い面白そうです!全然知識ないのですが、googleのスプレッドシートって、あのweb上で共有できて、保存ボタンとかがなくて、つねにリアルタイムで保存されるとかってやつですよね?それにどうやってアクセスするんでしょうか??filenameステートメントでURLを定義するような感じですか?それともLIBNAMEとかかけれたりします?
      それで、いろんな違う場所からでも、プログラム変えずに常に最新のデータで実行できたら凄い便利ですね!!
      EXCELにはうんざりさせられることが多いので、よろしければ教えてください。

      削除