我輩はブロガーではない。ネタもまだない

SASとかDelphiあたりの人様の役に立たないネタを提供します

SASのFAQが古い(INPUT関数)

twitterでは定期的にSASからFAQの情報が流れてきます。

昨日見たのは以下のFAQですが、ちょっと気になったので、調べてみました。
文字値の検証

内容は、「ある変数を数値変数に変換したいが、数字や文字が保存されており、
input関数を直接使用すると以下のNOTEが出力されてしまうが、これを抑制したい」
というもの。

NOTE: 無効な関数INPUT の引数が行100 カラム11 にあります。


これに対し、提示されているプログラム例は以下でした。

DATA source ;
  str = "123" ; OUTPUT;
  str = "AAA" ; OUTPUT;
  str = " " ; OUTPUT;
RUN;

DATA dest ;
  SET source ;
       /* 数字のみである場合、変数v は0 となります*/
  v = VERIFY(TRIM(str) , '0123456789');
  IF (v = 0) THEN
    num = INPUT(str, 8.);
  DROP v;
RUN; 

現実問題として、このようなデータにおいて数値変数に格納したい値には、純粋な数字
だけでなく、「10.5」のような数値は含まれないのでしょうか。
もし含まれない、もしくは純粋な「数字」のみを数値変数に格納したいのであればこの
プログラムで問題ありませんが、上記のままでは小数点を含む値は欠損になります。

これに対する解答は以下の通りです

DATA dest ;
  SET source ;
  num = INPUT(str, ??8.);
RUN; 

・?または??とは
以下、リファレンスより
SAS® 9.4 関数と CALL ルーチン リファレンス
SAS(R) 9.3 Functions and CALL Routines: Reference
無効なデータ値が読み取られた場合にエラーメッセージと入力行を非表示にする、オプションの疑問符(?)と二重疑問符(??)修飾子を指定します。?修飾子は、無効なデータメッセージを非表示にします。??修飾子は、無効なデータメッセージを非表示にし、無効なデータが読み取られたときに自動変数_ERROR_が 1 に設定されることを防ぎます。


input関数で指定するインフォーマットを8.とすると、数値に変換しようとします。この時、
数値に変換できないと、すでに記載したとおり、NOTEが表示され、さらに
_ERROR_=1がセットされ、ログに以下のように出力されます。

<span style="color: #2196f3">NOTE: 関数INPUT(行 144 カラム 9)の引数は無効です。</span>
str=AAA num=. _ERROR_=1 _N_=3

インフォーマットを?8.とするとNOTEは出力されず、

str=AAA num=. _ERROR_=1 _N_=3

だけになります。

インフォーマットを??8.とするとNOTEは出力されず、_ERROR_=1がセットされなくなるためログには不都合な情報が一切出力されなくなります。


他に、数値に変換できない場合は「0」にしたい、という場合は

DATA dest ;
  SET source ;
  IF INPUT(str, ??8.)=. then num=0;
  ELSE num = INPUT(str, 8.);
RUN; 

こんな感じでしょうか。

転職して古い(v6やv8.2の)ドキュメントにアクセスできなくなってしまったので、このメッセージ抑制機能がいつからあるか分かりませんが、すくなくとも9.1.3には存在するようです。

例えばバージョン別の解法を検索できるとか、もう少しFAQをupdateしてほしいと思っています。