一対多のマージで、一側データ由来の変数値を各BYグループの最初のみに出力したい事ってありませんか?
*** サンプルデータ ; data DT1; input A$ B$ C$ @@; cards; 001 aa cc 002 bb dd ;
data DT2; input A$ D @@; cards; 001 11 001 22 001 33 002 44 002 55 ;
|
やりたい事
上のデータをMERGEすると、
上記のように一側データ(DT1)由来の黄色部分が繰り返されますが、これを空白にしたい。
方法1 最初に思いつく方法
方法2 OUTPUT と CALL MISSING のコンボ技
紹介しといてなんですが、方法1の方が、分かり易くていいと思います。
ですが方法2のようなやり方を知ってると、応用がきいて便利な時があります。
方法2の解説
上記のように一側データ(DT1)由来の黄色部分が繰り返されますが、これを空白にしたい。
A
|
B
|
C
|
D
|
---|---|---|---|
001 | aa | cc | 11 |
001 | 22 | ||
001 | 33 | ||
002 | bb | dd | 44 |
002 | 55 |
前提:
一対多のマージを前提とします。多対多を含むマージ(一対多対多とか)だと挙動が変わってくるので今回の記事では対象外とします。
方法1 最初に思いつく方法
data OUT1; merge DT1 DT2; by A; if first.A = 0 then call missing( B, C ); run; |
以下記事で紹介した「FIRST.BY変数」を利用しています。
1つ注意として、ここで使用している「FIRST.BY変数」は「サブセット化IF」と一緒に使用すると正しく動かなくなりやすいです。
(解説記事:「サブセット化IFでありがちな落とし穴」)
方法2 OUTPUT と CALL MISSING のコンボ技
data OUT1; merge DT1 DT2; by A; output; call missing( B, C ); run; |
ですが方法2のようなやり方を知ってると、応用がきいて便利な時があります。
方法2の解説
以前の記事 「MERGEステートメントの落とし穴」 で紹介した内容を理解することで、今回の内容も理解がしやすいです。
重要なポイントは、
「一対多のマージにおいて、一側データセットの変数は、BYグループ毎に1回しかPDVに読み込まれない。
(BYグループが変わるまで、PDVに残った値が保持される。。。RETAINのようなイメージ)」
一側データの変数の数が多い場合は、「call missing( of _all_ );」と書いてしまえば、いっぺんに欠損値に出来るので楽です。
RETAIN等、値を保持するような処理は全て無効になります。
。。。つづく
重要なポイントは、
「一対多のマージにおいて、一側データセットの変数は、BYグループ毎に1回しかPDVに読み込まれない。
(BYグループが変わるまで、PDVに残った値が保持される。。。RETAINのようなイメージ)」
そこで、1オブザベーション毎に
① 「output;」でデータセットOUT1に出力
② 「call missing( B, C );」 でPDVの中の変数BとCを欠損値にする
① 「output;」でデータセットOUT1に出力
② 「call missing( B, C );」 でPDVの中の変数BとCを欠損値にする
PDVに残った一側データ由来の変数BとCの値が保持されるのを②によって抑制しているので、BYグループの最初にしかBとCが入らなくなっているわけです。
一側データの変数の数が多い場合は、「call missing( of _all_ );」と書いてしまえば、いっぺんに欠損値に出来るので楽です。
data OUT1; merge DT1 DT2; by A; output; call missing( of _all_ ); run; |
ただし、PDV内の全変数を欠損値にしているので、
0 件のコメント:
コメントを投稿