Compareプロシジャの結果が一致か不一致か、何が不一致かをマクロ変数で取得する話

コンペアプロシジャで、解析用データセットとかをいっぱいコンペアするときに、ひとつなぎで結果がでてくると見にくいし、スクロールだるいし、そもそもSASアウトプットもhtmlも見づらいので
僕はデータセットごとにコンペア結果をodsでPDFファイルにしたりします。
コンペアすると、いつもだいたい僕が間違ってますが、ダブルやってるもう一人の人が間違ってる場合に印刷してあげやすいしね。

そのときに、一致している場合はファイル名の頭にOK、してない場合はNGをつけるって処理を書いてたんですね。

あらじめOK_XX.pdfで出力しといて、NGの場合に
rc=rename(...\OK_XX.pdf,...\NG_XX.pdf,'file')みたいな感じです。

それはいいんですけど、コンペアが一致したかどうかの判定をods outputで
CompareSummaryとか諸々をだして、その中の文言で判定するという方法でやるしか知りませんでした。
バージョンによってなんか文言が微妙に変わるし、効率的じゃないなと思ってましたが、
最近、コンペアプロシジャの結果を自動マクロ変数で取得できるっていうことを教えていただきました。いや~、しらんかった。

&sysinfoを使います。

こいつはコンペアプロシジャの実行後に展開した場合、完全に一致してれば0が入り、値や属性など何かしら不一致であれば0以外の数がでます。

では見てみましょう。

データセット3つ用意します

data a;
x=1;
run;

data b;
x=1;
run;

data c(label="aaa");
x=2;y=1;output;
x=2;y=1;output;
format x yymmdds10.;
run;

一致している場合、

proc compare base=a comp=b;
run;

%put sysinfoの中身は → &sysinfo;

結果







不一致の場合、

proc compare base=a comp=c;
run;

%put sysinfoの中身は → &sysinfo;





となります。

で、気になるのが不一致だった場合、どんな不一致がでているのかを全部だせるのかという話ですが、band関数という2つの引数のビットごとの論理積を返す関数を使ってメッセージを分離できます。

では実際に、それを組み込んだコンペアマクロを見てみましょう。

%macro compare(main,sub);

 %if %sysfunc(exist(&main)) ne 1 %then %do;
  %put WARNING:メイン側&main.がないぞ;
 %end;
 %if %sysfunc(exist(&sub)) ne 1 %then %do;
  %put WARNING:サブ側&sub.がないぞ;
 %end;

 %if %sysfunc(exist(&main)) and %sysfunc(exist(&sub)) %then %do;
proc compare base=&main comp=⊂
run;
%put NOTE:&main.と&sub.コンペアしました;
%if %sysfunc(band(&sysinfo,1)) eq 1
         %then %put WARNING:データセットラベルが違うぞ
[Data set labels differ];
%if %sysfunc(band(&sysinfo,2)) eq 2
%then %put WARNING:データセットのタイプが違うぞ ビューとかコンペアしてんのか?
[Data set types differ];
%if %sysfunc(band(&sysinfo,4)) eq 4
%then %put WARNING:インフォーマット違うぞ
[Variable has different informat];
%if %sysfunc(band(&sysinfo,8)) eq 8
%then %put WARNING:フォーマット違うぞ
[Variable has different format ];
%if %sysfunc(band(&sysinfo,16)) eq 16
%then %put WARNING:レングス違うぞ
[Variable has different length];
%if %sysfunc(band(&sysinfo,32)) eq 32
%then %put WARNING:ラベル違うぞ
[Variable has different label];
%if %sysfunc(band(&sysinfo,64)) eq 64
%then %put WARNING:メイン側なんかobs数多いぞ
[Base data set has observation not in comparison];
%if %sysfunc(band(&sysinfo,128)) eq 128
%then %put WARNING:メイン側なんかobs数少ないぞ
[Comparison data set has observation not in base];
%if %sysfunc(band(&sysinfo,256)) eq 256
%then %put WARNING:BY変数でメインにだけあるやつあんぞ
[Base data set has BY group not in comparison];
%if %sysfunc(band(&sysinfo,512)) eq 512
%then %put WARNING:BY変数でメインにないやつあんぞ
[Comparison data set has BY group not in base];
%if %sysfunc(band(&sysinfo,1024)) eq 1024
%then %put WARNING:メイン側変数多いぞ
[Base data set has variable not in comparison];
%if %sysfunc(band(&sysinfo,2048)) eq 2048
%then %put WARNING:メイン側変数少ないぞ
[Comparison data set has variable not in base];
%if %sysfunc(band(&sysinfo,4096)) eq 4096
%then %put WARNING:値が違うね
[A value comparison was unequal];
%if %sysfunc(band(&sysinfo,8192)) eq 8192
%then %put WARNING:型の違う変数があるね
[Conflicting variable types];
%if %sysfunc(band(&sysinfo,16384)) eq 16384
%then %put WARNING:BY変数一致してないね
[BY variables do not match];
%if %sysfunc(band(&sysinfo,32768)) eq 32768
%then %put WARNING:コンペア自体コケてるやん。論外
[Fatal error: comparison not done] ;
%if &sysinfo eq 0 %then %put OKおめでとう!!;
 %end;
%mend compare;

%compare(a,c)



というわけです。
[]の中の英語がSASの公式のメッセージで、日本語はメインに非があるという体で僕が適当に書きました。これをうまく使うと、差異を把握しやすいのでコンペア・修正・すり合わせの作業がちょっと楽になるかもしれませんね。

コンペア状況一覧とか作って、細かく進捗管理してるぜ~って感じだすと、
あんまり進んでなくても、ウケがよかったりします

あ、Luaでもかけますからね

2 件のコメント:

  1. 今使っているマクロで同じようなことをしてるのでその紹介をブログでしようと思います.引用させてくださいね(^-^)lueでかいたほうがいいかな?

    返信削除
  2. 有難うございます!適当な記事で申し訳ないですが、是非是非。
    Luaで書かれていれば僕はハッピーですけど、一般的には需要ないので、マクロの方が広く世のためになるかもですね!!

    返信削除