DS2の方がより仕組みが洗練されている感じがします。
感覚的な話で終わってもいけないので、代表的なfindメソッドでその違いを見てみましょう。
以下の2つのデータセットがあって
data Q1;
X=1;Y=1;output;
X=1;Y=2;output;
X=2;Y=2;output;
X=3;Y=1;output;
run;
data Q2;
A=2;B=2;C=1;D=4;output;
A=3;B=1;C=2;D=3;output;
A=1;B=1;C=3;D=2;output;
A=3;B=3;C=4;D=1;output;
run;
ここでQ1のX,YとQ2のA Bをひも付けて、Q1にQ2からCとDを取得して、
それぞれV Wという変数に割り当てろという処理を考えてみます。
ハッシュオブジェクトなら、以下のようになります。
data A1;
if 0 then set Q2;
set Q1;
if _N_=1 then do;
declare hash h1(dataset:'Q2');
h1.definekey('A','B');
h1.definedata('C','D');
h1.definedone();
end;
if h1.find(key:X,key:Y) ^=0 then do;
call missing(of C D);
end;
V=C;
W=D;
drop A B C D;
run;
if h1.find(key:X,key:Y) ^=0 then do;
call missing(of C D);
end;
の箇所について、ちょっと小洒落た書き方をしていますが、そもそも
なぜこんな書き方をするのかというと
単純にh1.find(key:X,key:Y);とすると、キーが見つからない2行目がエラーになって
データセットが作成されません。
rc=h1.find(key:X,key:Y);とすればエラーにはなりませんが、直前の成功行の値が引延されてしまいます。
まあ、そのへんの話は
記事:ハッシュオブジェクトの世界①
などで断片的に説明しているので今回は割愛。
ただ、キーマッチしない場合のことを考えなきゃならなくて面倒だということはわかってください。
また、注目なのはV=C;W=D;の2行。割当ステートメントではなくrenameで処理してもいいんですが
昔から、このリネーム処理を果てしなく無駄に感じていました。keyの方はkey:指定で、データステップでの変数とハッシュオブジェクトのkey変数の変数名が異なっても寄せることはできますが、dataの方はできないんですよね。
さて、いよいよDS2で書いてみます。
proc ds2 libs=work;
data A4(overwrite=yes);
declare double A B C D X Y V W;
declare package hash h1();
drop A B C D;
method init();
h1.dataset('Q2');
h1.keys([A B]);
h1.data([C D]);
h1.definedone();
end;
method run();
set Q1;
h1.find([X Y],[V W]);
end;
enddata;
run;
quit;
う、美しい。
h1.find([X Y],[V W]);のように、最初の引数でハッシュのキーに紐づく変数、次にデータに紐付ける変数を指定できます。
さらにキーマッチしない場合の処理を書かなくても、エラーにもならず、引き伸ばしも起きません。
この素晴らしさをどう伝えていいのかわからない。
0 件のコメント:
コメントを投稿