2015年1月21日水曜日

データセットを縦結合する際、変数名が同じでlengthが異なってたら、最大のlengthに合わせる便利技


長いタイトルですが、SQLのいいとこ取りした便利技の紹介です。


Sample Data

data DT1;
length  A $2.  B $1.;
input A$ B$ ;
cards;
01 a
02 b
02 b
;
run;

data DT2;
length  A $1.  B $2.;
input A$ B$;
cards;
3 cc
4 dd
;
run;

DT1
 B 
  01 
   a    
  02  
   b  
  02
   b  

DT2
 A  
B
   3   
  cc   
   4
  dd  


サンプルデータをまずSETで結合してみます。
data OUT1;
   set DT1 DT2;
run;

ログ
WARNING: 入力データセットによって、変数Bに複数の長さが指定されました。データの切り捨てが発生します。

 B 
  01 
   a   
  02  
   b  
  02
   b  
  3
   c  
  4
   d  

結果を見ると、変数Bの値が、一部文字切れしちゃってますね。


これは、
「set DT1 DT2」 で最初に指定したデータセットDT1にある変数のlengthが、結合後のデータセットに割り当てられるからです。


つまり、変数Bのlengthが、DT1は「$1」、DT2は「$2」と異なっていますが、
上記青字の性質によって、結合時に「$1」が割り当てられます。

なので、DT2から持ってきた変数Bは、length「$1」に合わせて文字を切ってしまいます。


解決法

正攻法として、SETする時にlengthを設定しなおせばokですが、、、

data OUT2;
   length A B $3.;
   set DT1 DT2;
run;



SQLプロシジャ入門14:データセットを縦結合する【UNION】」で紹介した「OUTER UNION CORR」を使えば、
なんと結合するデータセットの中で最大のlengthを勝手に設定してくれます。

proc sql;
   create table OUT3 as
   select * from DT1
      outer union corr
   select * from DT2;
quit;

 B 
  01 
   a   
  02  
   b  
  02
   b  
  3
   cc  
  4
   dd  



ただし、SETステートメントと異なる動きあり。


まず、以下のプログラムと結果を見てみましょう。
*** Sample Data ;
data DT1;
   A = .;
run;

data DT2;
   format A yymmdd10. ;
   A = '01jan2015'd ;
run;

DT1
      A        
         .  

DT2
 A  
 2015-01-01 


*** SETステートメントによる結合 ;
data OUT1;
   set DT1 DT2;
run;

 A 
          .
  2015-01-01 


*** 「OUTER UNION CORR」による結合 ;
proc sql;
   create table OUT2 as
   select * from DT1
      outer union corr
   select * from DT2;
quit;

       A        
           .
      20089 

2つの結合結果を比較してみると、2行目の値が異なってますね。

これは「SETステートメント」の方は、format 「yymmdd10」 が割り当てられていて、
「OUTER UNION CORR」の方は、formatが割り当てられてないというだけで、
値自体は同じものです。


リファレンスから探せなくて確かではないですが、結合したデータセットの format, informat は、
  • 「SETステートメント」: 最初のデータセットDT1にformat, informatが割り当てられてなければ、次のデータセットDT2のformat, informatを割り当てている模様。
  • 「OUTER UNION CORR」: 最初のデータセットDT1のものを割り当てている模様。

他にも差異があるかもしれません。
利用する際はいろいろテストしたり、期待通りの結果になるかご確認ください。


この違いを気にしないシチュエーションであれば、超便利なテクニックですね。

0 件のコメント:

コメントを投稿