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
;












* PROC FREQで「ORDER=FORMATTED」 ;
proc freq data=DT1 order=formatted;
  tables A;
run;


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



原因

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

以下のプログラムで変数Aに割り当てられているフォーマットをログに出力してみると、

data _null_;
  set DT1;
  x=vformat(A);
  put x;
  stop;
run;

ログ
BEST12.


数値変数の場合、フォーマットが割り当てられていないと、内部的に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 件のコメント:

コメントを投稿