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

【訂正補足】coalesceとcoalescec

間違えました。訂正です。

UPDATEステートメントを使ってみる の中でSQL文


proc sql noprint;
 create table UP3 as
  select coalesce(TRA.X,MAS.X) as X
              ,coalescec(TRA.Y,MAS.Y) as Y
  from MAS full outer join TRA 
           on MAS.X=TRA.X;
quit;

を紹介して
数値にはcoalesce、文字にはcoalescecと書いたのですが、
それはデータステップ内で使用する場合でした。

もちろん上記コードで間違いなく実行できるのですが
SQLプロシジャ内で使用する場合、coalesce関数は本来、標準SQLで型を問わず使用できる
関数なので、それが反映され

proc sql noprint;
 create table UP3 as
  select coalesce(TRA.X,MAS.X) as X
              ,coalesce(TRA.Y,MAS.Y) as Y
  from MAS full outer join TRA 
           on MAS.X=TRA.X;
quit;

のように「c」をつける必要ないのでした。

うかつでした。

UPDATEステートメントを使ってみる

SASで結合といえば、なんだかんだいってやっぱりMergeステートメントが幅を利かせています。
書きようによって、多対多のようなケースを除いて、ほぼ全ての結合を表現できます。
Merge最高!Merge万歳!
が、場合によっては、UPDATEステートメントを使用した方が見通しがよい場合もあるので紹介します。
ちなみに僕はMergeステートメントあまり好きでありません

今データセット「MAS」と「TRA」があったとします。
UPDATEステートメントはマスタ―データセットとトランスザクションデータセットという考え方を持ち、
マスターをトランザクションで更新するといった機能になります。

data MAS;
 X=1;Y='あ';output;
 X=2;Y='ろ';output;
 X=3;Y='';output;
 X=4;Y='に';output;
run;

【MAS】


data TRA;
 X=1;Y='い';output;
 X=2;Y='';output;
 X=3;Y='は';output;
 X=5;Y='ほ';output;
run;

【TRA】







とりあえず X でソートします。
proc sort data=MAS;
 by X;
run;
proc sort data=TRA;
 by X;
run;



上の二つから以下の結果が欲しいとします。








変数Xをキーにして単純にMergeで結合するとTRAの変数Yがnullのため
結果のX=2に対応するYはnullになります。TRAにwhereでY^=''をつければいいのですが
そんなひと手間かけなくても

data UP;
 update MAS
        TRA;
     by X;
run;

で詰みです。
UPDATEステートメントはトランザクションデータセットにおいて値がnullの場合は
マスターデータセットの該当変数を上書きしないという付加機能を有するわけです。

ちなみに

data UP2;
 update MAS
        TRA updatemode=nomissingcheck;
     by X;
run;

のようにupdatemode=nomissingcheckとすると欠損値でも更新するので
すなわち

data MG;
 merge MAS
        TRA;
     by X;
run;

と同じになります。

ちなみにUPDATEと同様の表現が可能なMODIFYステートメントがいるのですが、
こいつは多機能で、深いので、いつか勉強してから紹介します。
LIBNAME EXCELで値とエクセルにだす時以外、あんまり使ったことないので、、

ちなみに今回のケース、SQLなら

proc sql noprint;
 create table UP3 as
  select coalesce(TRA.X,MAS.X) as X
              ,coalesce(TRA.Y,MAS.Y) as Y
  from MAS full outer join TRA 
           on MAS.X=TRA.X;
quit;


こんな感じでしょうか?
僕の好きなcoalesce関数です。coalesceの順番がトランザクション→マスターなところが味噌ですか。
あとfull outer joinは両側外部結合です。どっちかにでもあればとってくるよというやつです





詰めSAS3回目_最初にnullでない変数の値を取得する

変数を順番にみていって、null以外が初めて出現する際の値を取得する。また全ての変数がnullである場合、特定の値を代入する。
詰めSAS3回目は少し変わった処理になります。

問題は以下のデータセット

data Q3;
length A B C D $2.;
A='';B='ろ';C='';D='に';output;
A='い';B='ろ';C='は';D='に';output;
A='';B='';C='は';D='に';output;
A='';B='';C='';D='に';output;
A='';B='';C='';D='';output;
run;









について、A→B→C→Dとみていき、nullでない最初の値、すべてnullの場合は「へ」と返し
目的局面図









のようなデータセットを作成します。



【解法1】
data A1;
length E $2.;
 set Q3;
  E=coalescec(A,B,C,D,'へ');
 keep E;
run;

第一感として、配列とdo loopで処理する方法があると思うのですが
最短最善はcoalesce関数(今回は対象が文字変数なのでcoalescec)だと思っています。
引数のうち、指定順にnullでない最初のものを返します。
もともとSQLで使われていた関数のSASへの輸入だと思いますが、こいつは非常に優秀な
関数で、横方向への順次走査のような処理を関数でできてしまいます。定数をつかえば
最終的にnullの場合に定数を与えることができます。
たとえば臨床試験で、CRFにチェックボックスがいくつかあるもので、
よく、一つでもチェックがあれば何かのフラグをたてるといった処理がありますが
これをつかえば、ifステートメントを書き連ねる必要がなくなります。
ちなみにcoalesceはコアレスと発音します。
僕はコールエッセ関数とずっと呼んでいて恥をかきました。コアレスなんて読めます?

【解法2】
data A2;
 set Q3;
  array AR{4} $ A B C D;
   do i=1 to 4;
    if AR{i}^='' then do;
    E=AR{i};
  leave;
   end;
  end;
  if E='' then E='へ';
 keep E;
run;

配列ならこんな感じでしょうか?実は最近までleaveステートメントの存在を知りませんでした。
配列を抜けるときに使うのですね。