2018年3月13日火曜日

SASでトランプを作る



SGPLOTでトランプ作ってみました。

以下のような感じで1枚ずつ、マーク4種類 × 数字13枚 = 52枚のトランプがグラフとして出力されます。


出力結果の一部を切り貼りした寄せ集め



プログラム


※SAS9.4で動作します。バージョンや環境などで結果が綺麗に出力されないとかあるかもしれません。

ハッキリいってプログラムとしては汚いです。とりあえず作ったって感じです。
あとジョーカーを含めるとプログラムが複雑になっちゃうので、やめました。やるとしたらsymbolimageステートメントとか使って好きな画像をトランプの絵柄にしてジョーカーにする感じになります。


/*** トランプの数字とマークの表示位置をデータ化 ***/
data CARD;
    input SYMBOL:$7. NUMBER:$5. X Y;
    TOP_X     = 1.5;
    TOP_Y1    = 14;
    TOP_Y2    = 12.5;
    BOTTOM_X  = 3.5;
    BOTTOM_Y1 = 0;
    BOTTOM_Y2 = 1.5;
cards;
symbol1 1  2.5  7
symbol1 2  2.5  12
symbol2 2  2.5  2
symbol1 3  2.5  12
symbol2 3  2.5  2
symbol1 3  2.5  7
symbol1 4  2    12
symbol2 4  2    2
symbol1 4  3    12
symbol2 4  3    2
symbol1 5  2    12
symbol2 5  2    2
symbol1 5  3    12
symbol2 5  3    2
symbol1 5  2.5  7
symbol1 6  2    12
symbol2 6  2    2
symbol1 6  3    12
symbol2 6  3    2
symbol1 6  2    7
symbol1 6  3    7
symbol1 7  2    12
symbol2 7  2    2
symbol1 7  3    12
symbol2 7  3    2
symbol1 7  2    7
symbol1 7  3    7
symbol1 7  2.5  9.5
symbol1 8  2    12
symbol2 8  2    2
symbol1 8  3    12
symbol2 8  3    2
symbol1 8  2    7
symbol2 8  2.5  4.5
symbol1 8  3    7
symbol1 8  2.5  9.5
symbol1 9  2    12
symbol2 9  2    2
symbol1 9  2.5  6.999
symbol1 9  2    8.666
symbol2 9  2    5.333
symbol1 9  3    8.666
symbol2 9  3    5.333
symbol1 9  3    12
symbol2 9  3    2
symbol1 10 2    12
symbol2 10 2    2
symbol1 10 2.5  10.333
symbol2 10 2.5  3.666
symbol1 10 2    8.666
symbol2 10 2    5.333
symbol1 10 3    8.666
symbol2 10 3    5.333
symbol1 10 3    12
symbol2 10 3    2
symbol1 J  2.5  10
symbol1 J  3    10
symbol1 J  2.8  7.5
symbol1 J  2.8  5
symbol1 J  2.4  3.5
symbol1 J  1.9  4.5
symbol1 Q  2    10.5
symbol1 Q  2.5  11
symbol1 Q  3    10.5
symbol1 Q  3.2  8.5
symbol1 Q  3.2  6.5
symbol1 Q  3.05 3.85
symbol1 Q  2.5  4
symbol1 Q  2    4.5
symbol1 Q  1.8  6.5
symbol1 Q  1.8  8.5
symbol1 Q  2.75 5.8
symbol1 K  2    10.5
symbol1 K  2    8
symbol1 K  2    5.5
symbol1 K  2    3
symbol1 K  3    10.5
symbol1 K  2.8  8
symbol1 K  2.6  5.3
symbol1 K  3    3
;


/*** マーク別に1~Kまでのトランプを作成 ***/
%macro trump( unicode=, color= );


/* Attribute Map */
data MYMAP;
     ID="myid";
     VALUE="symbol1"; MARKERCOLOR="&color"; MARKERSYMBOL="symbol1"; output;
     VALUE="symbol2"; MARKERCOLOR="&color"; MARKERSYMBOL="symbol2"; output;
run;


/* Plot */
proc sgplot data=CARD noautolegend dattrmap=MYMAP;
     by NUMBER notsorted;

     xaxis min=-1 max=5   display=none;
     yaxis min=-1 max=15  display=none;

     /* トランプの形に線を引く */
     refline 1.2 3.8  / axis=x;
     refline -1 15 / axis=y;

     /* トランプのマークをUnicodeで取得 */
     symbolchar name=symbol1  char=&unicode;
     symbolchar name=symbol2  char=&unicode / rotate=180;

     /* トランプの左上の数字とマークをPlot */
     text    x=TOP_X    y=TOP_Y1    text=NUMBER  / textattrs=(size=0.6cm color=&color) ;
     scatter x=TOP_X    y=TOP_Y2                 / markerattrs=(symbol=symbol1 size=1.3cm color=&color);

     /* トランプの右下の数字とマークをPlot */
     text    x=BOTTOM_X y=BOTTOM_Y1 text=NUMBER  / textattrs=(size=0.6cm color=&color)  rotate=180 ;
     scatter x=BOTTOM_X y=BOTTOM_Y2              / markerattrs=(symbol=symbol2 size=1.3cm color=&color) ;

     /* トランプの真ん中のマークをPlot */
     scatter x=X        y=Y                      / attrid=myid  markerattrs=(size=2.1cm) group=symbol;

run;

%mend;

%trump( unicode='2660'x, color=black )  /* スペード */
%trump( unicode='2663'x, color=black )  /* クラブ */
%trump( unicode='2665'x, color=red   )  /* ハート */
%trump( unicode='2666'x, color=red   )  /* ダイヤ */




2018年3月8日木曜日

【SYMBOLGENオプション】展開したマクロ変数の値をログに表示する



「なんのオプションか分からないけど、みんな使ってるから自分も使っとくか」みたいなパターンが多いのがこの「symbolgenオプション」





   options symbolgen;


って書くと、プログラム実行時に展開されたマクロ変数の値がログに表示されます。



例①
%let x=123;
%put &x;


ログ
SYMBOLGEN:  マクロ変数 X を 123 に展開します。
123



例②
%macro test( ds=, out=, by=);

    proc sort data=&ds out=&out;
       by &by;
    run;

%mend;

%test( ds=sashelp.class, out=work.out1, by=name );


ログ
SYMBOLGEN: マクロ変数 DS を sashelp.class に展開します。
SYMBOLGEN: マクロ変数 OUT を work.out1 に展開します。
SYMBOLGEN: マクロ変数 BY を name に展開します。




元に戻すには


   options nosymbolgen;



2018年3月5日月曜日

PROC FORMATの「PICTUREステートメント」で気をつけたい内部の動き



PROC FORMATのPICTUREステートメントはちゃんと内部挙動を理解しないと痛い目を見ます。
動きが独特なので、しっかり理解できてる人はSASマイスターとして認定してもいいくらいです。


※今回の内部挙動に関する説明は私の推測も入ってるのであしからず。。間違いがあったらご指摘ください。




PICTUREステートメントの動き

以下のフォーマットを例に内部の動きを説明していきます。

proc format;
   picture TEST1_
       0 - 100 = '009.00%';
run;


① まず、フォーマットをあてる変数に10のn乗を掛けます。(n = 定義した書式の小数点以下桁数)

今回定義した書式は '009.00%' です。小数点以下桁数は2桁で定義されてますよね。
なのでフォーマットをあてる変数に10の2乗を掛けます。


1.23 → 123
3.456 → 345.6
(小数点以下2桁部分を整数部分にシフトさせている。)


②結果から小数部分を切り捨てます。
123 → 123
345.6 → 345


③この値を、定義した書式に右からあてはめていきます。

'009.00%' の数字セレクタ部分に右から数値をあてはめると、
123 → 001.23% →「  1.23%」
345 → 003.45% →「  3.45%」





「ROUND」「MULTIPLIER」オプションの動き


以下のフォーマットを例に内部の動きを説明していきます。

proc format;
   picture TEST2_ (round)
      0 - 100 = '009.00%' (multiplier=10) ;
run;


①まず、フォーマットをあてる変数には10のn乗を掛けずに、multiplier=オプションに設定した数を掛けます。


今回は「multiplier=10」なので
1.23 → 12.3
3.456 → 34.56


②roundオプションを指定している場合、小数部分を切り捨てではなく四捨五入します。

12.3 → 12
34.56 → 35


③この値を、定義した書式に右からあてはめていきます。

'009.00%' の数字セレクタ部分に右から数値をあてはめると、
12 → 000.12% →「  0.12%」
35 → 000.35% →「  0.35%」



実践


例えば、以下の変数Xには何かの割合が格納されているとします。

data DT1;
   input X;
   cards;
0.123
1
0.456
0.6789
;
run;

X
 0.123 
 1 
 0.456 
 0.6789 


このXを「0.123 → '12.3%'」 のように百分率にした上で%をつけたいとします。
今回解説した内容を踏まえると以下のようになるかと思います。

proc format;
   picture TEST3_ (round)
      0 - 1 = "009.0%" (multiplier=1000);
run;

data DT2;
   set DT1;
   length PCT $30.;
   PCT = put(x,TEST3_.);
run;

X 
 PCT 
 0.123
  12.3% 
 1 
 100.0%
 0.456
  45.6%
 0.6789 
  67.9%



厄介なケース


内部で10のn乗とか計算してることによって、小数点誤差が発生する可能性があります。

「小数点誤差?」って人は以下参照
http://sas-tumesas.blogspot.jp/2014/03/blog-post_14.html(データステップ100万回)


小数点誤差が問題になる例
proc format;
    picture TEST4_
       0 - 999 = '009.000000000' ;
run;

data DT3;
    X = 2.01;
    length Y $30.;
    Y = put(X,TEST4_.);
run;

X 
 Y 
 2.01 
   2.009999999 

「2.01」が「  2.00999…」となってしまいます。


以下のようにROUNDオプションで四捨五入しとけば一応は「2.01」と表示されますが、、

proc format;
    picture TEST4_ (round)
       0 - 999 = '009.000000000';
run;

data DT3;
    X = 2.01;
    length Y $30.;
    Y = put(X,TEST4_.);
run;

X 
 Y 
 2.01 
   2.010000000 

以下の最後の方で説明している通り、ROUNDしとけばOKというわけでもないのでご注意下さい。
http://sas-boubi.blogspot.jp/2016/03/put-floating-point-error.html


2018年3月1日木曜日

PROC FORMAT入門5 : PICTUREステートメント



PICTUREステートメント1」の続きです。
(基本的な動きを知らない方はまず上記の記事をご確認下さい)


PICTUREステートメントで小数を扱う時に使用する「ROUNDオプション」の説明をしていきます。





* PICTUREフォーマットの定義 ;
proc format;
   picture TEST1_
      0 - 100 = '009.00%'
   ;
   picture TEST2_ (round)
      0 - 100 = '009.00%'
   ;
run;


・「ROUNDオプション」をつけると四捨五入してくれます(今回は書式を '009.00%' と定義したので、小数点以下第3位を四捨五入し、第2位まで表示するようにしています)


・「ROUNDオプション」をつけないと切り捨てになります(今回は書式を '009.00%' と定義したので、小数点以下第3位を切り捨てし、第2位まで表示するようにしています)


・オプションの組み合わせ・使用方法によっては、動作しなかったり動きが変わるため要挙動確認!
その他、ミスりやすい挙動について、記事の最後のほうに解説記事のリンクを載せているのでご参照下さい。






では、適当なデータを作って、FORMAT変換後の結果を見てみましょう。

* Sample Data ;
data DT1;
   input X;
   cards;
12
12.34
12.345
;

* Format変換してみる ;
data DT2;
   set DT1;
   length Y1 Y2 $20.;
   Y1 = put(X,TEST1_.);
   Y2 = put(X,TEST2_.);
run;

 X  Y1  Y2 
12 
  12.00%   12.00% 
12.34 
  12.34%   12.34%
 12.345 
  12.34%  12.35%


ここまでそんなに難しくないですよね。
でも実は内部ではちょっと複雑な動きをしています。

とくにPICTUREステートメントで小数を扱う場合に、ちゃんと内部の動きを理解してないと想定外な結果になり痛い目を見ます(以下リンク参照)

(http://sas-boubi.blogspot.jp/2018/03/proc-formatpicture.html)






PROC FORMAT入門 : 記事一覧

2. INVALUEステートメント
3. 範囲の指定

2018年2月20日火曜日

PROC FORMAT入門4 : PICTUREステートメント




「PICTUREステートメント」は、
1→001、12→012」とか「1234→12-34、5678→56-78」のように数値に特定の書式を割り当てます。



📝 前置き


構文

PROC FORMAT;
      PICTURE フォーマット名
          数値  =  '書式の定義'  (オプション)
          数値  =  '書式の定義'  (オプション)
          ・・・
      ;
RUN;

  • フォーマット名の末尾は数字NG(例えば「TEST1」など)
  • 等号の左辺の「数値」の指定方法は、VALUEステートメントの数値フォーマットに対する指定方法と同じ
    • 等号の右辺の「書式の定義」と「オプション」の指定方法については以下詳しく解説していきます。




    * PICTUREフォーマットの定義 ;
    proc format;
       picture NINE
           0 - high = "99-99"
       ;
       picture ZERO
           0 - high = "00-00"
       ;
    run;

    • フォーマット「NINE」を定義して、出力する値の書式を '99-99' としています。9の意味は「先頭の数値がないところを0で埋める」という意味で、今回の場合は「123→"01-23"」や「1→"00-01"」のように変換


    • フォーマット「ZERO」を定義して、出力する値の書式を '00-00' としています。0の意味は「先頭の数値がないところを半角スペース(空白)で埋める」という意味で、今回の場合は「123→" 1-23"」や「1→"    1"」のように変換


    この書式設定に使う 0 や 9 を「数字セレクタ」といいます。
    (1 ~ 8 も 9 と同じ意味を持つ数字セレクタです)

    '00-99' のように 0 と 9 の組み合わせ方によって挙動が変わるので、そこんところは挙動確認必須です!
    また、数字セレクタ設定時は 'xyz99-99' のように先頭を数字セレクタ以外の文字にすることは出来ません。



    ではフォーマットを使ってみます。

    * Sample Data ;
    data DT1;
    input X;
    cards;
    1
    12
    123
    1234
    12345
    ;

    * フォーマット変換してみる ;
    data DT2;
       set DT1;
       length NINE ZERO $10.;
       NINE = put(X,NINE.);
       ZERO = put(X,ZERO.);
    run;
     X  NINE  ZERO 
     00-01      1
       12 
     00-12    12
      123 
     01-23  1-23
      1234 
     12-34 12-34
      12345 
     23-45 23-45


    気をつけたいのが、今回「数字セレクタ」の部分を「00-00」のように4桁しか定義してないから、最後のオブザベーションの結果が「12345→23-45」って感じで桁が足りなくて「1」が切れちゃってるとこですかね。





    PICTUREフォーマットのオプション


    ※オプションの組み合わせ・使用方法によっては、動作しなかったり動きが変わるため要挙動確認!

    オプション内容プログラム例
     ( NOEDIT )

    0~9を数字セレクタではなく、文字として扱う
    proc format;
      picture test2_
      0 - high = '00-00' (noedit);
    run;

    フォーマット変換の例
    「123」→「00-00」
    「1」    →「00-00」

     ( PREFIX = '文字' )

    フォーマット変換した値の先頭に表示する文字の指定
    ※「default=オプション」を併用しないと文字切れする可能性あり
    詳細は記事の下の方で解説
    proc format;
      picture test3_ (default=5)
      0 - high = '0000' (prefix='-');
    run;

    フォーマット変換の例
    「123」→「 -123」
    「1」    →「   -1」

     MULTIPLIER = 数値 )

    フォーマット変換前に変数値に掛ける数値を指定
    ※ただし以下リンクの通り、かなり取扱い注意なオプション
    (http://sas-boubi.blogspot.jp/2018/03/proc-formatpicture.html)
    proc format;
      picture test4_
      0 - high = "0000" (multiplier=10);
    run;

    フォーマット変換の例
    「123」→「1230」
    「1」    →「  10」

     ( FILL = '文字' )

    右の例のように数字セレクタで「00-00」みたいに指定した事で、
    フォーマット変換後に先頭が半角スペース(空白)となった部分を
    指定文字で埋める
    ※「default=オプション」と併用すると
    何故か「fill=」の指定文字が先頭に1つ強制付与される事がある

    proc format;
      picture test1_
      0 - high = '00-00' (fill='*');
    run;

    フォーマット変換の例
    「123」→「*1-23」
    「1」    →「****1」





    PREFIXオプションだけ詳細説明しときます。
    たとえば以下にマイナスの値を含むデータがあります。

    * Sample Data ;
    data DT3;
    input X;
    cards;
    -12
    12
    ;
     X 
    -12 
     12 



    このデータを以下のようにフォーマット変換すると、、

    * Mistake (間違っている例) ;
    proc format;
       picture TEST1_ (default=3)
         low - high = '00'
       ;
    run;

    data DT4;
       set DT3;
       length Y $20.;
       Y = put(X,TEST1_.);
    run;
     X  Y 
    -12 
      12 
     12 
      12 

    数値部分だけになり、マイナス記号が消えてしまいます。



    ならば、'-00' という書式を用意してみますが、、

    * Mistake (間違っている例) ;
    proc format;
       picture TEST1_ (default=3)
         low -< 0 = '-00'
         0 - high = '00'
       ;
    run;

    data DT4;
       set DT3;
       length Y $20.;
       Y = put(X,TEST1_.);
    run;
     X  Y 
    -12 
      12 
     12 
      12 

    やっぱりマイナス記号消えちゃいます。
    PICTUREフォーマットは、'-00' みたいに「書式の先頭に文字を入れてもその文字は無視される」という仕様になっています。



    てことで、先頭に文字を入れたい場合は、prefixオプションを使います。

    * 正しい例 ;
    proc format;
       picture TEST1_ (default=3)
         low -< 0 = '00' (prefix="-")
         0 - high = '00'
       ;
    run;

    data DT4;
       set DT3;
       length Y $20.;
       Y = put(X,TEST1_.);
    run;
     X  Y 
    -12 
     -12 
     12 
      12 


    ちなみに「picture TEST1_ (default=3)」って感じで、defaultオプションというのを指定しないと文字切れするケースがあるのでご注意を!

    これは「デフォルト長 (Default Length)」というものが関係してます。
    例えば、今回の例で defaultオプションがない状態で実行すると、、

    proc format;
       picture TEST1_
         low -< 0 = '00' (prefix="-")
         0 - high = '00'
       ;
    run;

    等号の右側に定義した値 "00" の文字の長さは2バイトです。
    PICTUREステートメントではこの長さが「デフォルト長」というものになります。
    (定義した値が複数ある場合は、右側の文字の長さが最も大きいものがそのフォーマットの「デフォルト長」になる)


    このデフォルト長となった2バイトが、フォーマット適用後の長さになります。
    どういう事かというと、例えば変数値が「-12」の時、適用されるフォーマットは以下太文字部分のやつですが、、

    proc format;
       picture TEST1_
         low -< 0 = '00' (prefix="-")
         0 - high = '00'
       ;
    run;

    フォーマット適用後の文字値 "-12" から「デフォルト長の2バイト」に切られた "12" という文字値になってしまいます。
    このような文字切れを起こさないために defaultオプションでデフォルト長を指定する必要があります。

    ちなみに、defaultオプションにも少し注意が必要で、例えば「default=10」と指定すると
    変数値「12」→ フォーマット変換後の値「        12」
    って感じでdefaultオプションの長さの分だけ幅が確保された上で右詰めにされた値になります。



    2018年2月15日木曜日

    ODS OUTPUT の落とし穴 (2)



    以下記事の続き。
    ODS OUTPUT の落とし穴 (1)



    以下のプログラム、WARNINGが出ちゃいますが、どこがおかしいか分かりますか?

    proc glm data=sashelp.class;
       class sex;
       model height = sex;
    run;

    ods output Summary=OUT1;
    proc means data=sashelp.class;
       var height;
    run;
    ods output close;


    ログ
    WARNING: 出力'Summary'は作成されていません。出力オブジェクト名、ラベル、パスが正しく記述されているかを確認してください。また、要求した出力オブジェクトを作成するために、
             適切なプロシジャオプションが使われているかも確認してください。たとえば、NOPRINTオプションが使われていないことを確認してください。
    WARNING: プロシジャステートメントの終わりを検出したので、現在のODS SELECT/EXCLUDE/OUTPUTステートメントをクリアしました。
             対話型プロシジャ(終了するにはquit;をタイプします)が終了していないかもしれません。



    この落とし穴にはまってる人たまに見かけます。


    これは対話型プロシジャを使う場合に起こる落とし穴です。
    (対話型プロシジャについては、「RUNとQUITの違い」をご覧ください。)


    今回の例で使用しているGLMプロシジャは対話型プロシジャです。
    「QUIT」と書くか、別のDATAステップ・PROCステップが現れるまで、GLMプロシジャは起動したままになります。
    なので、以下の青文字部分がGLMプロシジャに対する処理だと判断されてしまいます。


    proc glm data=sashelp.class;
       class sex;
       model height = sex;
    run;

    ods output Summary=OUT1;
    proc means data=sashelp.class;
       var height;
    run;
    ods output close;



    解決方法はご存じの通り、「quit;」を入れるだけです。

    proc glm data=sashelp.class;
       class sex;
       model height = sex;
    run;
    quit;

    ods output Summary=OUT1;
    proc means data=sashelp.class;
       var height;
    run;
    ods output close;




    そもそもSASのマニュアルにも対話型プロシジャにQUITを入れていない例があるので、
    この問題に気づかなくても無理はないっちゃないんですが。。


    ちなみに、今回紹介した落とし穴は「ods output」だけでなく、「ods select」「ods exclude」とかでも同様に起こる問題です。

    2018年2月6日火曜日

    PROC FORMAT入門2 : INVALUEステートメント




    今回は「INVALUEステートメント」について。
    データを読み込む際、以下の変換をする「インフォーマット」と呼ばれるものを定義するステートメントです。

    • 文字値から数値(例:男→1→2
    • 文字値から文字値(例:Y→YES、N→NO


    ※ INVALUEステートメントの重要な性質(落とし穴)についても、解説記事のリンクを最後の方に載せてるので、そちらも要確認!



    実際、例を見た方が分かり易いです。まずは変換を行うインフォーマットの定義から。



    インフォーマットを定義する例

    proc format;

       invalue TEST1_
          "MALE"     = 1
          "FEMALE" = 2
       ;
       invalue $TEST2_
          "Y"    = "YES"
          "N"    = "NO"
       ;
    run;

    • 「TEST1_」というインフォーマットを定義し、「"MALE"→1、"FEMALE"→2」 という変換を定義(数値に変換するインフォーマットを「数値インフォーマット」という)

    • 「TEST2_」というインフォーマットを定義し、「"Y"→"YES"、"N"→"NO"」 という変換を定義(文字値に変換するインフォーマットを「文字インフォーマット」という)



    構文
    PROC FORMAT;

          INVALUE インフォーマット名
             値  =  変換後の値
             値  =  変換後の値
             ・・・
         ;
    RUN;


    ポイント
    • インフォーマット名の最後は数字じゃダメ(例えば「TEST1」など)
    • 「"Y"→"YES"」のような文字から文字への変換を行うインフォーマットは、インフォーマット名の先頭に「$」をつける(例えば「$TEST」など)



    では、先程つくったインフォーマットを使ってみましょう。


    インフォーマットを使う例①

    data DT1;
       length SEX 8. YN $3.;
       input SEX YN;
       informat SEX TEST1_. YN $TEST2_.;
    cards;
    MALE Y
    FEMALE N
    ;
     SEX  YN 
      1  YES 
      2  NO


    CARDSで読み込むデータに対して「INFORMATステートメント」で以下を行なっています。

    • インフォーマット「TEST1_」を使い「"MALE"→1、"FEMALE"→2」に変換した値を変数 SEX に格納
    • インフォーマット「TEST2_」を使い「"Y"→"YES"、"N"→"NO"」に変換した値を変数 YN に格納



    構文
    INFORMAT  変数名  インフォーマット名. ;


    ポイント
    • テキストファイル や CARDS で読み込むデータに対して、インフォーマット変換した値を変数に格納する。
    • インフォーマット名の後ろにドット「.」を入れる必要があります。




    インフォーマットを使う例②

    * Sample data ;
    data DT1;
       length SEX $6. YN $1.;
       SEX="MALE"; YN="Y"; output;
       SEX="FEMALE"; YN="N"; output;
    run;

    SEX  YN 
     MALE  Y
     FEMALE  N


    * 変数値をインフォーマットで変換する ;
    data DT3;
       set DT1;
       length SEX2 8. YN2 $3.;
       SEX2 = input( SEX, TEST1_.);
       YN2  = input( YN , $TEST2_.);
    run;

    SEX 
     YN 
     SEX2 
     YN2 
     MALE
     Y 
      1
     YES 
     FEMALE  
     N
     
     NO



    上の例では「INPUT関数」を使って以下を行なっています。
    • 変数 SEX の値を インフォーマット「TEST1_」を使って変換し、変数 SEX2 に格納。
    • 変数 YN の値を インフォーマット「TEST2_」を使って変換し、変数 YN2 に格納。



    構文
    新規変数名 = INPUT(  変数名 ,  インフォーマット名.  );


    ポイント
    • 文字変数に対して、インフォーマットを使って数値または文字に変換します。
    • インフォーマット名の後ろにドット「.」を入れる必要があります。




    注意が必要なインフォーマットの細かい挙動

    proc format;

       * (1) 数値インフォーマット1 ;
       invalue X1_ (default=20)
          "1" = 111
          other = 999
       ;
       * (2) 数値インフォーマット2 ;
       invalue X2_ (default=20)
          1 = 111
          other = 999
       ;
       * (3) 文字インフォーマット1 ;
       invalue $X3_ (default=20)
          "1" = "111"
          other = "999"
       ;
       * (4) 文字インフォーマット2 ;
       invalue $X4_ (default=20)
          1 = "111"
          other = "999"
       ;
    run;

    * インフォーマットで変換 ;
    data DT4;
       length X $20. X1 X2 8. X3 X4 $20.;
       X = "+1.0";
       X1 = input(X,X1_.);
       X2 = input(X,X2_.);
       X3 = input(X,$X3_.);
       X4 = input(X,$X4_.);
    run;

    X 
     X1 
     X2 
     X3 
     X4 
     +1.0 
     999  111  999  999 


    上で作成した (2) のインフォーマットだけ、変換した結果が異なります。
    これは以下のような文字値から数値に変換する「数値インフォーマット」かつ青文字部分の定義で「左側に指定した数値をクォーテーションで囲っていない」場合、、

    proc format;
     invalue X2_ (default=20)
      1 = 111
      other = 999
     ;
    run;

    数値としてマッチした値に対して変換することが出来ます。
    例えば、文字変数Xの値「+1.0」を数値化すると「+1.0」→「1」なので、上の青文字部分の定義とマッチするので変換が行われます。

    その他の (1) (3) (4) で作成したインフォーマットでは、左側に指定した数値をクォーテーションで囲う・囲わない関係なく、文字値としてマッチした値のみ変換します。

    (ちなみに、上の例で「default=オプション」を指定しているのは、以下の注意事項の2個目で解説しているデフォルト長による落とし穴予防のためです)




    注意事項・落とし穴

    • インフォーマットで「文字値の欠損値」を表す場合「" " = "欠損値"」のような指定になります(「""」ではなく「" "」というように間に半角スペースを入れないと欠損値の意味にならない)
    • INFORMATの落とし穴【デフォルト長】




    PROC FORMAT入門 : 記事一覧

    2. INVALUEステートメント
    3. 範囲の指定