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オプションの長さの分だけ幅が確保された上で右詰めにされた値になります。



    0 件のコメント:

    コメントを投稿