ラベル 関数: COALESCE の投稿を表示しています。 すべての投稿を表示
ラベル 関数: COALESCE の投稿を表示しています。 すべての投稿を表示

2017年5月26日金曜日

My Favorite SAS Functions (5) COALESCE / COALESCEC関数


第5回目は、COALESCE / COALESCEC関数。
お気に入り関数トップ3のうちのひとつです(あと2つは WHICHN、CHOOSEN)

この関数は「引数のうち最初に欠損値以外で登場する値を返す」という機能を持っています。


基本的な構文や機能は以下記事で紹介済みなので、そちらをご覧ください。
http://sas-boubi.blogspot.jp/2016/04/coalesce.html

データステップ100万回でも特集されてます。
http://sas-tumesas.blogspot.jp/2013/09/sas3null.html





上の過去記事でさんざん例を紹介済みな感じですが、あらためて。
以下X1~X3の中から最初に欠損値以外で登場する値を返したいとします。

  X1  
  X2  
  X3  
   

  aa  bb  aa  



以下、COALESCEC関数を使わない場合(Before)と、使う場合(After)。

Before
  length Y $2.;
         if X1^="" then Y=X1;
  else if X2^="" then Y=X2;
  else if X3^="" then Y=X3;

After
  length Y $2.;
  Y = coalescec( X1,X2,X3 );


いいですね~このスッキリ感がたまらないですね。

ちなみにCOALESCE関数あるあるだと思うんですが、読み方が最初よく分からなくて、綴りをいちいち調べてた時期がありました。

コアレスと読むそうです。
上にリンク貼ったSASYAMAさんの記事でもコールエッセって読んでたってお話しがありますね。
私はコアレスシって読んでました。



記事一覧

1.CATS関数
5.COALESCE・COALESCEC関数

2016年4月26日火曜日

プログラムスリム化計画 【COALESCE関数を活用する】


覚えたら絶対役に立つCOALESCE関数を紹介。


構文


  COALESCE関数( 引数1 , 引数2 ・・・ )


この関数は引数のうち最初に欠損値以外で登場する値を返してくれる。
引数が全て数値の場合「COALESCE」、全て文字の場合「COALESCEC」と使い分ける必要がある。


それではどんな時使えるのか、簡単な例を示します。

サンプルデータ

data DT1;
length YN 8. A B C $10.;
input YN A$ B$ C$;
cards;
0 . aa bb
1 . . cc
. . . .
;
run;

  YN   
  A   
  B   
  C  
   0      aa    bb  
   1         cc  
   .           


例①

サンプルデータに、有無変数YN 「0:なし、1:あり」 があります。
この変数が欠損値だったら 「99:不明」 と置き換えた変数YN2を作りたいとします。

  YN   
  YN2   
   0    0
   1    1
   .   99


通常以下のように書きますが、、
data OUT1;
   set DT1;
   if YN^=. then YN2 = YN;
   else YN2 = 99;
   keep YN YN2;
run;


COALESCE関数を使えば、一発です。
data OUT2;
   set DT1;
   YN2 = coalesce( YN, 99 );
   keep YN YN2;
run;





例②

以下のロジックで変数Xを導出したいとします。

・ Aに値があれば X =  A
・ 上記以外で、Bに値があれば X = B
・ 上記以外で、Cに値があれば X = C
・ 上記以外(すべて欠損値)なら X = "XXX"

  A  
  B   
  C   
  X  
     aa    bb    aa  
        cc    cc  
         XXX 

通常以下のような書き方になりますが、、
data OUT3;
   set DT1;
   length X $10.;
   if A^="" then X = A;
   else if B^="" then X = B;
   else if C^="" then X = C;
   else X = "XXX";
   keep A B C X;
run;


これも一発で書けます。
data OUT4;
   set DT1;
   length X $10.;
   X = coalescec( A, B, C, "XXX" );
   keep A B C X;
run;



他にも以下のような使い方など、工夫次第で色々な使い方ができる超便利な関数です。
変数指定は「V100-V1」のように逆にもできる。


2014年6月13日金曜日

変数指定は「V100-V1」のように逆にもできる。


変数がV1、V2・・・V100とあったとき、「keep V1-V100」みたいに範囲指定して書けることはわりと知られています。
これはさらに「keep V100-V1」のように逆に指定することもできます。

この逆指定で処理が楽になる例を以下にあげてみました。

サンプルデータのNO1からNO3の中で最後の値を取ってきたい場合、
COALESCE関数と変数逆指定の組み合わせで簡単に出来てしまいます。

*** サンプルデータ作成 ;
data DT1;
input SUBJID:$3. NO1 NO2 NO3;
cards;
001 100 95 110
002 56  50 .
003 90 .  .
;

*** 変数の逆指定 ;
data DT2;
  set DT1;
  LAST = coalesce( of NO3-NO1 );
run;

 SUBJID   NO1   NO2   NO3   LAST 
  001    100   95   110   110 
  002   56  50   .  50
  003   90   .   .   90

変数の範囲指定を関数で行う場合「of」を先頭につけるのを忘れずに!


2014年4月11日金曜日

SQLプロシジャで結合条件を省略する方法。



(注意点もあるので最後までご覧ください)


SQLには「自然結合」という結合方法がある。
これはデータ間で共通する変数名を自動で結合条件に入れてくれます。


サンプルデータ作成

data DT1;
input A B;
cards;
1 10
2 20
;

data DT2;
input A C$;
cards;
1 AA
3 BB
;





例えば「FULL JOIN」でDT1とDT2を結合したいとする。

*** FULL JOIN ;
proc sql;
   create table DT3 as
   select coalesce( DT1.A, DT2.A ) as A,
              DT1.B,
              DT2.C
   from DT1 full join DT2 on DT1.A = DT2.A;
quit;

DT3
A  B   C
1  10  AA
2  20 
3  .     BB



さて、ここで「FULL JOIN」を自然結合に置き換えてみましょう。

  • 「FULL JOIN」は「NATURAL FULL JOIN」で自然結合になります。
    • データセット間で「共通する変数名」を自動で結合条件に設定してくれるので、FROMに結合条件は記述不要
    • ただし、データセット間で「共通する変数名」があってもデータセット間で型が異なっていると、ERRORになり、自然結合が失敗します。
    • SELECTも「SELECT *」でシンプルな記述にすることが出来ます。このように書くと、各データセットの全変数をSELECTしたうえで、データセット間で変数名が共通する場合はCOALESCE関数で1変数にまとめてくれます(よく分からんって方は、詳細を下の方でも解説してます)


    *** NATURAL FULL JOIN ;
    proc sql;
       create table DT3 as
       select  *
       from  DT1 natural full join  DT2;
    quit;

    DT3
    A  C   B
    1  AA  10
    2         20 
    3  BB   .

    「FULL JOIN」と「NATURAL FULL JOIN」の結果を比較すると、変数の順番が違ってますが、それ以外の結果は同じですね。



      解説

      上の「NATURAL FULL JOIN」の例は、内部で以下のようなプログラムに置き換えられます。


      proc sql ;
         create table  DT3 as
         select coalesce(DT2.A, DT1.A) as A,
                   DT2.C,
                   DT1.B

        from WORK.DT1 full outer join WORK.DT2 on DT2.A = DT1.A;
      quit;

      • まずFROMの「NATURAL FULL JOIN」が「FULL OUTER JOIN (FULL JOIN)」に置き換わっています。
      • またデータセット間で共通する変数名AがFROMの結合条件に自動で設定されました。
      • 次にSELECTでは、共通変数AをCOALESCE関数で1変数にまとめてくれてます。この関数は「引数のうち最初にNULL以外で登場する値」を返してくれる。

      (余談:データステップでは、引数が全て数値の場合COALESCE関数、全て文字の場合COALESCEC関数、と使い分ける必要があるけど、SQLの場合は引数が全て数値または全て文字のどちらでもCOALESCE関数が使える)


      ちなみに、
      今回は「FULL JOIN」を自然結合に置き換える例でしたが、以下の通り他の結合方法も自然結合に置き換えることが出来ます。
      • 「INNER JOIN」→「NATURAL INNER JOIN」
      • 「LEFT JOIN」→「NATURAL LEFT JOIN」
      • 「RIGHT JOIN」→「NATURAL RIGHT JOIN」
      • 「FULL JOIN」→「NATURAL FULL JOIN」



      お役立ち情報

      以前紹介した「FEEDBACK」オプションを使って、自然結合がどのような文に展開されているのか、ログに展開することが出来ます。

      proc sql feedback;
         create table DT3 as
         select  *
         from  DT1 natural full join  DT2;
      quit;

      ログ
      select COALESCE(DT2.A, DT1.A) as A, DT2.C, DT1.B
        from WORK.DT1 full outer join WORK.DT2 on DT2.A = DT1.A;




      注意

      自然結合は便利だけど、、もし一方のデータセットに変数を追加した場合、
      もう一方のデータセットに同じ変数名が存在してると、新たにその変数も自動で結合条件に入ってしまい、当初と異なる動きをしてしまう。


      対策として、
      例えば、以下のように必要な変数のみKEEP等で保持しておけば、上記のような不測の事態にも備えることが出来ます。

      proc sql;
         create table DT3 as
         select  *
         from  DT1 (keep=A B)  natural full join  DT2 (keep=A C);
      quit;

      こういった不確定要素もあるので、自然結合を用いる際は、最大限の注意を払う必要があります。



      注意その2

      SQLプロシジャの 「NATURAL JOIN」 で3つ以上のデータセットを結合すると意図した結果にならない。