2015年3月23日月曜日

PROC MEANSの、COMPLETETYPES・PRELOADFMTオプションの紹介



注意点もあるので最後までご覧ください。
まずは以下のプログラムと結果を見てみましょう。

*** サンプルデータ作成 ;
data DT1;
input A B;
cards;
1 10
1 20
3 30
3 40
3 50
;
 A 
B
  1  
  10 
  1
  20 
  3
  30
  3
  40  
  3
  50  

*** FORMAT作成 ;
proc format;
   value MYFMT
   1 = "aaa"
   2 = "bbb"
   3 = "ccc"
 ;
run;

*** Bの要約統計量を、Aの値毎に出す ;
proc means data=DT1 nway;
   var  B;
   class  A;
   format  A  MYFMT. ;
run;



Bの要約統計量を、Aの値毎に出しています。
その際、Aに以下のフォーマットをあてています。
「1="aaa"」「2="bbb"」「3="ccc"」


OUTPUTを見てみると、「2="bbb"」の要約統計量が出てませんね。
これはデータセットDT1のAに「2="bbb"」の値が存在しないからです。


そこで、以下のように completetypes と preloadfmt オプションを使って再度実行してみると、フォーマットに存在するカテゴリ値をすべて出力してくれます。


proc means data=DT1 nway completetypes;
   var  B;
   class  A / preloadfmt ;
   format  A  MYFMT.;
run;



注意点その1

集計対象が0オブザベーションの場合、今回のオプションは機能しません。


注意点その2

以下のようにフォーマットに欠損値を定義して、MEANSの結果に欠損値のカテゴリも出したい場合、MEANSプロシジャでmissingオプションをつけないと出てくれません。

proc format;
   value MYFMT
   . = "Unknown"
   1 = "aaa"
   2 = "bbb"
   3 = "ccc"
 ;
run;

proc means data=DT1 nway completetypes;
   var  B;
   class  A / missing preloadfmt ;
   format  A  MYFMT.;
run;



注意点その3

以下リファレンスのMEANSプロシジャのCLASSステートメントのページで「PRELOADFMT」>「Interaction」の欄に気になる記述が。


CLASSが文字変数だと、非常に低いまたは高い「sentinel values」が生成されるかも、だそうです。
「sentinel value」はプログラミング用語で「番兵」とかって表現される特別な値らしいです。
SASの内部処理の話なので、ちょっと分かりづらいですね。


SASのテクニカルサポートにも聞いてみました。
聞いてみたうえで、やはり内部的な話なので、ハッキリと分かったわけではないんですが、

こう書いたとき結果がおかしくなるっていう例を以下に示します。

proc format;
   value $x
      "x" - high = "xx"
   ;
run;

data DT2;
   length x $40.;
   x = "x";
   y = 1;
run;

proc means data=DT2 nway completetypes noprint;
   var y;
   class x / preloadfmt;
   format x $x.;
   output out=OUT1 n= mean= / autoname;
run;

OUT1(SAS Ondemand for Academicsで開いたときの画面です😟


おかしいです。
上の例では、まずFORMATプロシジャの「high」に対する「sentinel value」がカテゴリとして扱われてしまうようです。

この「sentinel value」ですが、上の結果のイメージではxの2行目のところで「?」と出ていて、これはSASのセッションエンコーディングで有効な文字ではないため。

上の結果のイメージは、SAS Ondemand for Academicsで見たときのものです。
他の環境によっては、使用しているSASのセッションエンコーディングで有効な文字ではない場合に、見た目上は欠損値に見えるので、余計混乱のもとになりそうです。

あと、色々試してみましたが、この問題に起因した問題がまだあるような気がしました。
ひとまず、こういう使い方をする場合は注意が必要そうです。そもそもリファレンスにこの事について記載されてるってことはバグではなく仕様ってことなんでしょうか。修正してほしい。。



0 件のコメント:

コメントを投稿