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

2017年7月27日木曜日

My Favorite SAS Functions (9) CALL MISSING



第9回目は、関数じゃなくてコールルーチンになりますが、CALL MISSINGを紹介。
指定した変数をすべて欠損値にする機能を持っています。


こちらもやっぱり過去記事で紹介済みです。
指定した変数をすべて欠損値にする【CALL MISSING】



さて、CALL MISSINGの使用前・使用後を見てみましょう。




以下のようなデータセットがあったとします。

data DT1;
   X1 = 123;
   X2 = 456;
   X3 = "abc";
run;
  X1  
  X2  
  X3   
 123 456  abc

ここで、変数 X1, X2, X3 を欠損値にしたいします。

普通に書くと以下のような感じですね。

Before
data DT2;
   set DT1;
   X1=.;
   X2=.;
   X3="";
run;
  X1  
  X2  
  X3  
   .   .  

数値変数だったら「数値変数=.;」
文字変数だったら「文字変数="";」
みたいな感じで書き方分けなきゃいけないし、面倒ですよね。

CALL MISSINGを使えば、もっと楽になります。

After
data DT2;
   set DT1;
   call missing(X1, X2, X3);
run;
  X1  
  X2  
  X3  
   .   .  

📝ちなみに

通常のデータセット以外で使用すると、WARNINGが出て機能しない事があるらしい?ので、ログとかも確認するようにして下さい

2016年6月7日火曜日

「OUTPUT」と「CALL MISSING」のコンボ技


一対多のマージで、一側データ由来の変数値を各BYグループの最初のみに出力したい事ってありませんか?


*** サンプルデータ ;
data DT1;
input A$ B$ C$ @@;
cards;
001 aa cc 002 bb dd
;

A
 B  
 C  
  001    aa     cc   
  002    bb  dd   

data DT2;
input A$ D @@;
cards;
001 11 001 22 001 33 002 44 002 55
;

A
  D  
  001     11   
  001     22
  001     33
  002     44
  002     55


やりたい事

上のデータをMERGEすると、
data OUT1;
  merge DT1 DT2;
  by A;
run;


上記のように一側データ(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」と一緒に使用すると正しく動かなくなりやすいです。



方法2 OUTPUT と CALL MISSING のコンボ技
data OUT1;
  merge DT1 DT2;
  by A;
  output;
  call missing( B, C );
run;

紹介しといてなんですが、方法1の方が、分かり易くていいと思います。
ですが方法2のようなやり方を知ってると、応用がきいて便利な時があります。


方法2の解説

以前の記事 「MERGEステートメントの落とし穴」 で紹介した内容を理解することで、今回の内容も理解がしやすいです。

重要なポイントは、
「一対多のマージにおいて、一側データセットの変数は、BYグループ毎に1回しかPDVに読み込まれない。
(BYグループが変わるまで、PDVに残った値が保持される。。。RETAINのようなイメージ)」


そこで、1オブザベーション毎に
① 「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内の全変数を欠損値にしているので、
RETAIN等、値を保持するような処理は全て無効になります。


。。。つづく

2016年2月18日木曜日

指定した変数をすべて欠損値にする【CALL MISSING】


CALL MISSING を使うと、指定した変数をまとめて欠損値にできます。


構文


  CALL MISSING( 変数1, 変数2, ・・・)


  • 数値変数と文字変数まとめて指定可能
  • 通常のデータセット以外で使用すると、WARNINGが出て機能しない事があるらしい?ので、ログとかも確認するようにして下さい。詳細不明なので、何かご存じの方いたら、教えて下さい




*** サンプルデータ ;
data DT1;
  length A1 A2 8. A3 $10.;
  A1=1;
  A2=2;
  A3="aaa";
run;
  A1  
  A2  
  A3   
    1    2  aaa

*** まとめて欠損値にする ;
data DT2;
  set DT1;
  call missing( A1, A2, A3 );
run;
  A1  
  A2  
  A3   
    .    .  


さらに of を使えばいっぺんに変数指定が可能。

call missing( of A1-A3 );  
→ A1~A3まで連番の変数すべて
(「of」をつけ忘れると「A1-A3」で引き算の意味になっちゃうので注意)

call missing( of _all_ );
→ 全変数

call missing( of _numeric_ );
→全数値変数

call missing( of _character_ );
→全文字変数


2015年4月14日火曜日

「変数○○は初期化されていません」のメッセージは侮れない。



以下をご覧ください。

data DT1;
   length A 8.;
run;

ログ


ログにNOTEとして 「変数Aは初期化されていません」 と出ます。

これは「変数が作成されたのになにも値が与えられていない」ときに出てくるログです。
上の例では「変数Aを定義して作成したのに、なにも値が与えられていない」ということですね。


このように初期化されていない変数は、変数の枠だけ作られて、中身は欠損値になります。
ERRORとかWARNINGじゃないし放っとくか、となるかもしれませんが、このメッセージが役に立つ場合もあります。



たとえば、以下のプログラムを実行して、ログを見てみると、、

data DT2;
   length AAABBB 8.;
   AAABB = 1;
run;

ログ
NOTE: 変数AAABBBは初期化されていません。


初期化されていません」と出てしまいました。
あれ?「length AAABBB 8.」で属性定義した後、ちゃんと「AAABB = 1」で値をセットしてるのに、、、



しかしプログラムをよく見ると、

length AAABBB 8.;
AAABB = 1;


Bの数を1個間違えて書いてたことに気づきます。
このように変数名のタイプミスをしてしまった時などに、この初期化メッセージが気づかせてくれる事があるので、侮れません。
ていうか、私自身、結構やってしまうミスなので、いつも助けられてます。



ちなみに「属性定義だけして、中身は欠損値でいいんだけど、、初期化メッセージが出るのはヤダ。。」といった場合は、欠損値を与える事の出来る CALL MISSING が便利です。

data DT3;
   length A 8. B C $10.;
   call missing( A, B, C );
run;




続く(VARINITCHKオプションで、「変数○○は初期化されていません」をWARNINGやERRORにする。