PROC FORMAT の VALUEステートメントでありがちな落とし穴。
以下のプログラムと結果をご覧ください。結果は想定通りでしょうか?
proc format;
value $FMT "a" = "x" "abc" = "y" ; run; data DT1; format VAR1 $FMT.; VAR1 = "abc"; run;
|
変数VAR1は "abc" なのでフォーマット$FMTを貼りつけると "y" と表示されるはずが、 "x" が表示されてしまいました。
これは「デフォルト長 (Default Length)」というものが関係してます。
例えば、今回の例で
proc format;
value $FMT
"a" = "x"
"abc" = "y"
;
run;
等号の右側に定義した値 ("x" と "y") の文字の長さは1バイトです。
この長さが、そのフォーマットの「デフォルト長」というものになります。
(定義した値が複数ある場合は、右側の文字の長さが最も大きいものがそのフォーマットの「デフォルト長」になる)
そしてこのフォーマット$FMTは、以降のFORMATステートメントでデフォルト長となった1バイトしか視界に入らなくなります。
どういう事かというと、、
data DT1;
format VAR1 $FMT.;
VAR1 = "abc";
run;
変数VAR1 の値 "abc" から先頭の1バイトの値 "a" だけを見て対応するフォーマット値を表示しようとします。
ちょうど PROC FORMAT で "a" = "x" と定義してたので、この値が表示されちゃったというわけですね。
proc format;
value $FMT
"a" = "x"
"abc" = "y"
;
run;
ちなみに...
以下のように、PROC FORMATから1つ目の「"a" = "x"」をコメントアウトして定義から外すと、、、
proc format; value $FMT /* "a" = "x" */ "abc" = "y" ; run; data DT1; format VAR1 $FMT.; VAR1 = "abc"; run;
|
まずは変数VAR1 の値 "abc" から先頭の1バイトの値 "a" だけを見て対応するフォーマット値を表示しようとしますが、
対応するフォーマットがないので、そのままの値 "a" が表示されちゃってるわけですね。
この辺の挙動を知らないと「なんじゃこりゃ??」となってしまいますね。
変数VAR1 の値 "abc" の文字の長さは3バイトなので、3バイト全部読み込んで表示する必要があります。
解決策としては以下の2つの方法があります。
解決策①
proc format;
value $FMT (default=10) "a" = "x" "abc" = "y" ; run; data DT1; format VAR1 $FMT.; VAR1 = "abc"; run;
|
「DEFAULT=オプション」によってこのフォーマットのデフォルト長を 10 に広げています。
proc format;
value $FMT (max=10) "a" = "x" "abc" = "y" ; run; data DT1; format VAR1 $FMT10.; VAR1 = "abc"; run;
|
「format VAR1 $FMT10.」として、FORMATステートメントで、フォーマット名の後ろに幅を指定することも出来ます。
今回は幅を10に設定して問題なく動作していますが、「出力形式〇〇に指定した幅は無効です」みたいなERRORが出る事があります。そういった場合はFORMATプロシジャで「value $FMT (max=10)」というように、指定可能な幅の最大値を設定する必要があります。
インフォーマットでも同様の落とし穴があります。
INFORMATの落とし穴【デフォルト長】
ポイント
・文字値から数値に変換するINVALUEステートメントでは「左側」に定義した文字の長さがデフォルト長になる
・VALUEステートメントでは「右側」に定義した文字の長さがデフォルト長になる
0 件のコメント:
コメントを投稿