ラベル gennum= の投稿を表示しています。 すべての投稿を表示
ラベル gennum= の投稿を表示しています。 すべての投稿を表示

処理前後のデータセットの更新内容を確認するマクロ

昔、自分が書いたコードを整理していて、見つけたのですが、以下のマクロが結構面白かったです。

%macro updatecomp(base,update,key);
 proc datasets;
   modify &base(genmax=2);
 run;
 data &base;
  update &base &update;
  by &key;
 run;
 proc compare base=&base comp=&base(gennum=-1);
 run;
%mend;

マスターとなるデータを、更新用のデータでどんどん更新していく処理をしていた時に、SAS初心者で、怖かったため、実行の都度、どこがどのように更新されたかをアウトプットウインドウで確認したくて書いたみたいです。
全く覚えてなかったですが、初心者にしてはなかなか渋いコード書くなぁと感心しました。

genmaxとgennumについては

「世代管理機能でデータセットの更新履歴(更新前後のDS)を残す_GENMAX=オプション」
http://sas-tumesas.blogspot.jp/2013/11/dsgenmax.html

で紹介しています。

使い方としては

例えば

data Q1;
do X=1 to 30;
 Y='A';output;
end;
run;

data Q2;
 do X=1,3,15;
  Y='B';output;
 end;
run;

のような二つのデータセットがあって、
Xをキーとして、Q1のデータをQ2で更新したい場合、

%updatecomp(Q1,Q2,X)

とすると、Q1が更新され、アウトプットには








と、更新処理の前後の差異がでてきます。









世代管理機能でデータセットの更新履歴(更新前後のDS)を残す_GENMAX=オプション

SASは既に存在しているデータセットと同じ名前でデータステップを実行すると、既存の内容は消え、新しい内容に置き換わります。
古い内容を残すにはデータセット名を変えるしかない、、というわけではありません。
SAS8からGENMAX=オプションによる自動的な世代管理が可能です。
具体的にはデータステップでデータセットを作成する際にGENMAX=○をつけると○で指定した数字の分-1だけ、過去の状態をヒストリカルデータセットという形で自動保存してくれます。

今、genmax=3でデータセットQ1を作成します。

data Q1(genmax=3);
 X=1;Y='A';output;
run;













プロパティを見ると最大の世代数3、現在の世代1となっています。

そして再度Q1でデータセットを作成します

data Q1;
 X=1;Y='A';output;
 X=2;Y='B';output;
run;

すると










勝手に「Q1#001」というものが作成され、中身を見ると
更新前のデータセットの内容になっています。

もう一度作成します

data Q1;
 X=1;Y='A';output;
 X=3;Y='C';output;
run;
















さらに作成します。

data Q1;
 X=1;Y='A';output;
 X=4;Y='D';output;
run;















今、Q1のgenmaxは3なので、最新のQ1と二つのヒストリカルデータセットが保持されます。そのため、上記のように最も古いQ1#001は自動的に削除されます。

ちなみにこのデータセットはgennum=オプションを使って、データステップで指定できます。
1世代前のデータセットなら-1、2世代前なら-2とします。

data A1;
 set Q1(gennum=-1);
run;









ちなみに名前リテラルで直接指定もできますが、世代番号はどんどん変わっていくので、
1世代前といった指定はできません。

data A1;
 set 'Q1#003'n;
run;

今回は例なのでWORKにデータセットを作りましたが、通常は永久SASデータセットについて
行います。WORKにつくってもSAS閉じたら全部消えますからね。
よくあるのが、毎日結果を更新、つまり同名でデータセットを更新するプログラムで
何日か分の結果を残して置きたい時などです。
よく、昨日実行したときは、こうだった気がするけど、今日まわしたらこうだったから原因を調べて等と言われて、でも結果は最新しか残ってなかったりすると、ログからだけだとデバックが困難な場合もありますよね。そういった時も保険で、世代管理しておくと助かります。

よく使うのが
proc compare base=Q1 comp=Q1(gennum=-1);
run;

のようにして、どこが変わったか見たいときですね