2017年4月3日月曜日

「ORDER=FORMATTED」の落とし穴


前回の記事でORDER=オプションを紹介しました。
http://sas-boubi.blogspot.jp/2017/03/order_28.html


このオプションで一番注意しなければならないのが、「ORDER=FORMATTED」を指定した場合です。
以下の例が想定通りの結果になるか各自確認してみてください。


「ORDER = FORMATTED」 の挙動確認

* サンプルデータ ;
data DT1;
input A @@;
cards;
1 1 1.5 1.5 2 2
;
run;












* FREQプロシジャで「ORDER=FORMATTED」 ;
proc freq data=DT1 order=formatted;
  table A;
run;


あれ!?
特にフォーマットも割り当ててないし、「1→1.5→2」の順になるかと思ったら「1→2→1.5」になってる。。



原因

何故かというと、、
(ここから推測ですので間違ってるかもしれないのであしからず。)

数値変数の場合、フォーマットを割り当てないと、デフォルトでBEST12.が割り当てられます。
試しに以下のプログラムで変数Aに割り当てられているフォーマットをログに出力してみると分かります。
data _null_;
  set DT1;
  x=vformat(A);
  put x;
  stop;
run;

ログ
BEST12.


では、PUT関数を使って、変数AをBEST12.で文字変換してみましょう。
data DT2;
  set DT1;
  length A2 $20.;
  A2 = put(A,best12.);
run;


文字変換したA2を見ると、以下のように先頭に空白が入ってしまいます。
1    → "           1"
1.5 → "         1.5"
2    → "           2"

この文字変換したA2でソートしてみると、、
proc sort data=DT2;
  by A2;
run;


先頭の空白込みでソートしてしまうので、本来の数値の順番にソートがされないって事ですね。



プロシジャ毎にORDER=オプションのデフォルト設定が違う

大抵のプロシジャは「ORDER=INTERNAL」がデフォルトなので、あまり気にしなくていいのですが、例外があります。

私が知ってる例外はPROC REPORTです。
SAS9.4 (2016/4/3現在) では、デフォルトが「ORDER=FORMATTED」に設定されています。
proc report data=DT1;
 column A;
 define A / group;
run;








proc report data=DT1;
 column A;
 define A / order;
run;


順番おかしいですね。フォーマットではなく内部の数値の順に出力したい場合は、以下のように「ORDER=INTERNAL」を別途指定します。

proc report data=DT1;
 column A;
 define A / group order=internal;
run;
proc report data=DT1;
 column A;
 define A / order order=internal;
run;
SAS9.4のマニュアルには、PROC REPORTのORDER=は他のプロシジャと整合とるために今後のリリースでデフォルト設定を変えるかも、というような記述があるので、この点も要注意ですね。

0 件のコメント:

コメントを投稿