2016年5月31日火曜日

【%LET Y=%X】 みたいに書いて指定変数の統計量をマクロ変数に直接格納する方法





SASプログラミング掲示板で過去に以下の質問がありました。
http://tumesas.progoo.com/bbs/tumesas_topic_pr_20.html (サイト閉鎖されたためリンク切れ)


%let Y = %X(データセット, 対象変数 );


みたいな書き方で、「マクロ変数Yに統計量などを格納する事は出来ないか?」 という質問です。
この時、FCMPを使う方法を提案したんですが、もっといい方法を思いついたので、また自己満足のために書き留めておきます。



着想としては以下の記事あたり。
マクロで 【%LET Y=%X】 みたいな書き方
データステップ内でプロシジャを実行する。


以下は、SUMMARYプロシジャを実行して、好きな統計量を直接マクロ変数に落とすマクロです。

*** マクロ登録 ;
%macro m_summary( ds, var, stat );
/********************************************************************
   ds       … 対象データセット
   var      … 対象変数
   stat     … 統計量キーワード
********************************************************************/


/* dosubl関数で値を設定するマクロ変数_mputが既に存在していたら削除 */
/* (削除しないと_mputに正しい値が入らない事があったため) */
%symdel _mput / nowarn;


%local _rc _mput;
%let _rc = %sysfunc(dosubl(%str(


       /* SUMMARYプロシジャを実行 */
       proc summary data=&DS;
          output out=OUT1 &stat(&var)=_mvar1;
       run;

       /* 結果をマクロ変数に格納 */
       /* マクロ変数に数値をいれると、元の値と誤差がでる事があるので注意 */
       data _null_;
          set OUT1;
          call symputx('_mput', _mvar1);
       run;
)));

&_mput

%mend;


*** マクロを実行してみる ;
%let val=%m_summary( sashelp.class, age, mean );
%put &val;


*** データステップでも実行出来るようになってます ;
data DT1;
 VAL1 = %m_summary( sashelp.class, age   , mean );
 VAL2 = %m_summary( sashelp.class, height, mean );
run;



💬 注意事項
プログラム中に青字で書いてるように、dosubl関数内ではマクロ変数が正しく作られない場合があるので、実行後正しい結果が返ってくるか、テストが必要です


また「データステップ100万回」にて紹介されている通り、
マクロ変数に数値をいれると、元の値と誤差がでる事があるので注意。

マクロ変数に数値をいれて戻すと誤差がでちゃう場合がある問題について考える話



実用的かどうかは置いといて、個人的に満足したので良しとします。。
(アイディアの段階のため、この方法を利用する際は、上で記載した問題を考慮する必要があるのと、動作テストも行ったほうが良いです)



2016年5月26日木曜日

マクロ言語入門6:クォート処理【%BQUOTE関数】




%STR と %BQUOTE は同じクォート処理系の関数ですが、まったく異なる動きをします。



%STR関数の性質

%STRで囲った範囲の特殊文字をクォートする。



%BQUOTE関数の性質

%BQUOTEで囲った範囲に「クォート処理されていないマクロやマクロ変数」が含まれる場合は可能な限り展開してから、結果に含まれる特殊文字をクォートする。




具体例


以下は、変数Aに値を入れるマクロです。

%macro TEST( VAL );

       data DT1;
           length A $30.;
           A = "&VAL";
       run;

%mend;


このマクロを実行して変数Aに「A,B,C」という値を入れたいとします。

 
 A,B,C  


まどろっこしい書き方ですが、以下のように書いて実行すると、、

%let X= A,B,C;
%TEST( &X );

ログ
ERROR: マクロに定義された数よりも多い定位置パラメータが与えられています。

エラーが出ます。これは 「%TEST( &X );」 → 「%TEST( A,B,C );」という順に展開されるわけですが、
「%TEST(A,B,C)」にはカンマが含まれてるので「3つ引数があるのか」と解釈されてしまうからです。




%BQUOTE関数を使ってみる


マクロ変数Xを展開した後の値「A,B,C」をクォート処理したいので、%BQUOTE関数を使います。

%let X = A,B,C;
%TEST( %bquote(&X) );

 
 A,B,C  




%BQUOTE , %NRBQUOTE関数


%BQUOTE と %NRBQUOTE は同じ性質ですが、クォート対象の文字が異なります。

マクロ関数対象の文字
%BQUOTE






+ - * / < > = ¬ ^ ~ ; , # 半角スペース
AND OR NOT EQ NE LE LT GE GT IN ' " ( )

以下のようにクォートする文字としてカッコを含めて記述すると、SASが混乱してバグってしまうので注意
%bquote(aa(bb)
%bquote(aa)bb)
%NRBQUOTE




%BQUOTE関数と同じ+ & %

このマクロ関数は挙動を勘違いしやすいうえ、扱いづらいため個人的にはあまり使ってません。
以下「%NRBQUOTEの詳しい挙動」も要確認!



💬 %NRBQUOTEの詳しい挙動

例えば、以下2つのマクロ変数があったとします。
  • マクロ変数X: 「&Y」という値がクォート処理されずに格納されている
  • マクロ変数Y: 「&Z」という値がクォート処理されずに格納されている


これに対して、以下を実行すると、、

%put %nrbquote(&X);

%BQUOTE, %NRBQUOTEで囲った範囲の「クォート処理されていないマクロやマクロ変数」は可能な限り展開されるので、

→「&X」を展開すると「&Y」
→「&Y」を展開すると「&Z」
→「&Z」というマクロ変数は存在しないため、これ以上展開できない
→「&Z」を展開できない旨のWARNINGをログに出力


%NRBQUOTEは「&」もクォート対象になっているので、

→「&Z」というマクロ変数として解釈されないようクォート処理




実践例


%SYSFUNC関数を使う時によくクォート処理します。詳細は以下過去記事をご覧ください。



とにかくマクロ関数は複雑で、何故そうなるの?という挙動が沢山あります。
実際に使用する際は、結果をよく確認したほうが良さそうです。


2016年5月25日水曜日

最後のオブザベーションかどうかを判定する方法【END=オプション】





今日たまたまタイトルにあるような質問を3回別の方から頂いたので記念に。



やりたい事


以下のデータで、最後のオブザベーションを読み込んだ時に何かしたい。

サンプルデータ ;
data DT1;
  do X=1 to 5;
      output;
  end;
run;

 X  
   1  
   2 
   3  
   4  
   5  




方法


SETステートメントに END=オプションを指定する事で、
  •  最後のオブザベーションだったら「1」、それ以外は「0」が一時変数に入る。
  •  一時変数は出力データセットに残りません。


構文

  SET データセット名  END = 適当な一時変数名;








以下は最後のオブザベーションだったら変数FLGに「1」を入れる例。

data DT2;
   set DT1 end=EOF;
   if EOF=1 then FLG=1;
run;

 X  
 FLG 
   1  
  .  
   2 
  .  
   3  
  .  
   4  
  .  
   5  
  1





注意


以下のようにWHEREステートメントで絞ったうえで最後のオブザベーションを判定することは出来ますが、、

data DT3;
   set DT1 end=EOF;
   where X < 3;
   if EOF=1 then FLG=1;
run;

 X  
 FLG 
   1  
  .  
   2 
  1  


サブセット化IFを使ってる場合は、判定できないのでご注意ください。

data DT3;
   set DT1 end=EOF;
   if X < 3;
   if EOF=1 then FLG=1;
run;

 X  
 FLG 
   1  
  .  
   2 
  .  


後、POINT=オプションによるランダムアクセスを使用してデータセットを読み取っている場合、END=オプションは使用できない(正しく動作しない)ようなので注意。


2016年5月19日木曜日

マクロ言語入門5:クォート処理【%STR関数】





クォート処理とは?



以下は、変数Aに値を入れるマクロです。

%macro TEST( VAL );

       data DT1;
           length A $30.;
           A = "&VAL";
       run;

%mend;


このマクロを実行して変数Aに「A,B,C」という値を入れたいとします。

 
 A,B,C  


何も考えず書くと、、

%TEST(A,B,C);

ログ
ERROR: マクロに定義された数よりも多い定位置パラメータが与えられています。

エラーが出ます。これは%TEST(A,B,C)にカンマが含まれてるので「3つ引数があるのか」と解釈されてしまうからです。



解決策
%STR関数で囲ってあげます。

%TEST( %str(A,B,C) );

 
 A,B,C  


%STR関数は、カンマやセミコロンなどSASの構文として意味のある特定の文字を、ただの文字として解釈させる関数です。
このただの文字として解釈させる事を「クォート処理」といいます。





%STR, %NRSTR関数



関数によってクォート対象の文字が異なります。

マクロ関数対象の文字備考
%STR




+ - * / < > = ¬ ^ ~ ; , # 半角スペース
AND OR NOT EQ NE LE LT GE GT IN



' " ( )
上記文字をクォートしたい場合、その文字の前に%をつける(%直後の1文字のみに効果がある)
この方法の落とし穴を記事の下の方の例③に示しているので要確認!
%NRSTR

%STR関数と同じ+ & %

%STR関数と同じ



ちなみに%NRSTR の先頭の「NR」は 「Not Resolved」の意味で、つまり「マクロやマクロ変数を展開させない」という意味合いがあります。
なので&や%がクォート対象となっています。



では最初に書いたマクロTESTを使って、クォート処理の例を紹介します。
(例③④は落とし穴的な挙動なので要注意です!)






例①
欲しい結果
 
 Mr.&Mrs.Smith  

「&Mrs」 というマクロ変数として解釈されないようクォート処理をします。
%TEST( %nrstr(Mr.&Mrs.Smith);




例②
欲しい結果
 
 It's a small world  

シングルクォーテーションをクォート処理します。
%TEST( %str(It%'s a small world);



例③
欲しい結果
 
 100%JUICE  

「%JUICE」 というマクロとして解釈されないようクォート処理をします。
%TEST( %nrstr(100%JUICE);
   または
%TEST( %nrstr(100%%)JUICE );

2個目の例を「%TEST( %nrstr(100%)JUICE )」とすると、、

%NRSTR関数での「%)」は「)」をクォート処理せよという命令になってしまいます(%NRSTR関数の閉じカッコがクォート処理されるのでSASの挙動もおかしくなる)

そこで%STR, %NRSTR関数内に「%%」と書くと、
  • この「%」は直後の文字「'」「"」「(」「)」をクォートするという意味ではない、と命令する
  • 「%%」は「%」に置き換わる



例④
欲しい結果
 
 /* abcd */  

コメントステートメントとして解釈されないようクォート処理をします。
%TEST( %str(/)%str(*) abcd %str(*)%str(/) );

「%TEST( %str(/* abcd */) )」という書き方はNG。%STR関数の中でもコメントステートメントとして認識されるからです。なので「/*」を1文字ずつ%STR関数で分けてクォート処理しています。

ちなみに、コメントステートメントの種類(「/* */」「* ;」「%* ;」)によってマクロ内での挙動が異なっているのが影響してますが、
ほしい結果が「* abcd ;」の場合は「%TEST( * abcd ; )」という書き方でOK。
ややこしい。。コメントステートメントを含む文字をクォート処理する場合は挙動確認したほうが良いです。




(おまけ) シングルクォートとダブルクォート


以下プログラムは、&Mrsというマクロ変数が指定されてると解釈されてしまい、ログにWARNINGが出ます。

data OUT1;
  A = "Mr.&Mrs.Smith";
run;

ログ
WARNING: MRSのシンボリック参照を解決できません。


しかし、以下はWARNINGが出ず期待通りの結果が得られます。

data OUT2;
  A = 'Mr.&Mrs.Smith';
run;


これは「シングルクォーテーションで囲まれた文字に&や%が含まれていても、ただの文字として解釈される」というルールがあるからです。

2016年5月17日火曜日

データステップ内でプロシジャを実行する。



SASで遊んでる時に作ったマクロを自己満足のために載せたいと思います。


データステップ内でSUMMARYプロシジャ実行して、好きな統計量を変数に落とすマクロです。
以下「僕の頁」で紹介されているDOSUBL(SAS9.3以上)とFETCHOBSを使いました。

dosubl関数(call executeの兄弟)
fetchobs関数

*** マクロ登録 ;
%macro m_summary( ds, var, stat, newvar );
************************************;
* ds       … 対象データセット ;
* var      … 対象変数 ;
* stat     … 統計量キーワード ;
* newvar … 結果を格納する変数 ;
************************************;

   *** SUMMARYプロシジャを実行 ;
   _rc = dosubl("

       proc summary data=&ds;
          output out=_sumout1 &stat(&var)=_mvar1;
       run;

   ");

   *** 結果を取得 ;
   length _mvar1 8.;
   _mvar1=.;

   _dsid = open("_sumout1(keep=_mvar1)") ;
   call set(_dsid);
   _rc = fetchobs(_dsid,1);
   _rc = close(_dsid);

   &newvar = _mvar1;

   *** マクロ内で作った一時変数を削除 ;
   drop _rc _dsid _mvar1;

%mend;



*** データステップ内でマクロを実行してみる ;
data dt1;
   length avg_age avg_hei 8.;
   %m_summary( sashelp.class, age, mean, avg_age );
   %m_summary( sashelp.class, height, mean, avg_hei );
run;
 avg_age
avg_hei
 13.315789474  
  62.336842105 

※本マクロは粗削りな部分があるので、ご利用される場合は、マクロの内容を理解頂いて、適宜中身を修正ください。


ポイント
以下「データステップ100万回」で紹介されている通り、
マクロ変数に数値をいれると、元の値と誤差がでる事があるので、結果を取得する部分ではマクロ機能の使用を避けて、OPEN, FETCHOBS関数を使用してみました。

マクロ変数に数値をいれて戻すと誤差がでちゃう場合がある問題について考える話



以下につづく
【%LET Y=%X】 みたいに書いて指定変数の統計量をマクロ変数に直接格納する方法


2016年5月13日金曜日

マクロ言語入門4:パラメータの設定【キーワードパラメータ】



マクロに「キーワードパラメータ」というものを設定する方法を紹介します。





基本構文


マクロの登録
%MACRO  マクロ名( マクロ変数1=, マクロ変数2= ・・・ );

   ~プログラム~

%MEND;

  • 同名のマクロを同じ場所(カタログ)に複数作成することはできないので注意(上書きされる)
  • まず「%MACRO;」~「%MEND;」の中にマクロとして登録したいプログラムを書きます。
  • マクロ内で使用したいマクロ変数を「マクロ名」のカッコ内に列挙しておきます。




上記「マクロ名」のカッコ内に列挙したマクロ変数に対し、以下のように値を設定してマクロを実行します。

マクロの実行
%マクロ名( マクロ変数1=値, マクロ変数2=値 ・・・ )

  • マクロ変数に設定する値の両端に半角スペースを入れても、それらスペースはマクロ変数に含められません(別記事で解説する%STR関数を使用して含めることも可)
  • また、実行時「このマクロ名はNG」「このステートメントはマクロではNG」などのマクロのルールに違反している旨のログメッセージがないかも要確認です。




簡単な例

*** マクロ登録 ;
%macro TEST( DS= );
     proc print data=&DS;
     run;
%mend;

*** マクロ実行 ;
%TEST( DS=SASHELP.CLASS )
;


最終的に以下のプログラムが展開・実行されます。
proc print data=SASHELP.CLASS;
run;




パラメータに初期値を与える

*** マクロ登録 ;
%macro TEST( DS=SASHELP.CLASS );
     proc print data=&DS;
     run;
%mend;

*** マクロ実行 ;

%TEST();
%TEST(DS=SASHELP.IRIS);
%TEST(DS=SASHELP.RETAIL);



%macro TEST( DS=SASHELP.CLASS )」 で TESTマクロのマクロ変数DSに SASHELP.CLASS という初期値を与えています。


よってこのマクロを実行する際、

  • %TEST()」 でマクロ変数DS への値を指定しないと初期値 SASHELP.CLASS が使われて実行。
  • %TEST(DS=SASHELP.IRIS)」 でマクロ変数DS の値を SASHELP.IRIS に上書きして実行。
  • %TEST(DS=SASHELP.RETAIL)」 でマクロ変数DS の値を SASHELP.RETAIL に上書きして実行。

という動きをします。




記事一覧

1. マクロ変数とは
2. マクロの登録と実行
3. 定位置パラメータ
4. キーワードパラメータ
5. クォート処理
6. クォート処理2
7. ループ処理
8. 条件分岐処理
9. ドット
10. &&
11. 演算評価
12. 補足


2016年5月12日木曜日

マクロ言語入門3:パラメータの設定【定位置パラメータ】



マクロに「定位置パラメータ」というものを設定する方法を紹介します。





基本構文



マクロの登録
%MACRO  マクロ名( マクロ変数1, マクロ変数2 ・・・ );

   ~プログラム~

%MEND;

  • 同名のマクロを同じ場所(カタログ)に複数作成することは出来ないので注意(上書きされる)
  • 「%MACRO」~「%MEND;」の中にマクロとして登録したいプログラムを書きます。
  • マクロ内で使用したいマクロ変数を「マクロ名」のカッコ内に列挙しておきます。




上記「マクロ名」のカッコ内に列挙したマクロ変数に対し、以下のように値を設定してマクロを実行します。

マクロの実行
%マクロ名( マクロ変数値1, マクロ変数値2 ・・・ )

  • マクロ変数値の両端に半角スペースを入れても、それらスペースはマクロ変数に含められません(別記事で解説する%STR関数を使用して含めることも可)
  • また、実行時「このマクロ名はNG」「このステートメントはマクロではNG」などのマクロのルールに違反している旨のログメッセージがないかも要確認です。






*** マクロ登録 ;
%macro TEST( DS );
     proc print data=&DS;
     run;
%mend;

*** マクロ実行 ;
%TEST( SASHELP.CLASS )
;

  • %macro TEST( DS )」 で「TESTマクロにDSというマクロ変数があるよ」と教えておく。
  • %TEST( SASHELP.CLASS )」でマクロ変数DS に SASHELP.CLASS という値を当てはめて実行。


最終的に以下のプログラムが展開・実行されます。

proc print data=SASHELP.CLASS;
run;




記事一覧

1. マクロ変数とは
2. マクロの登録と実行
3. 定位置パラメータ
4. キーワードパラメータ
5. クォート処理
6. クォート処理2
7. ループ処理
8. 条件分岐処理
9. ドット
10. &&
11. 演算評価
12. 補足


2016年5月11日水曜日

マクロ言語入門2:マクロの登録と実行【%MACRO、%MEND】





データセットあるいは変数を変えて同じような処理を繰り返し実行したい場合、マクロを使うと便利です。
まずは基本構文から触れてみましょう。




基本構文



マクロの登録
%MACRO  マクロ名;

   ~プログラム~

%MEND;

  • 同名のマクロを同じ場所(カタログ)に複数作成することは出来ないので注意(上書きされる)
  • 「%MACRO」~「%MEND;」の中にマクロとして登録したいプログラムを書きます。



マクロの実行
%マクロ名

  • 登録したマクロを「%マクロ名」で実行する事が出来ます。
  • 実行時、「このマクロ名はNG」「このステートメントはマクロではNG」などのマクロのルールに違反している旨のログメッセージがないかも要確認です。




例①

*** マクロの登録 ;
%macro TEST;
   proc print data=SASHELP.CLASS;
   run;
%mend;

PRINTプロシジャでデータセットSASHELP.CLASSを出力するマクロTESTを登録しています。
このプログラムでマクロTESTは登録されますが、まだマクロの中身のプログラムは実行されません。



* マクロの実行 ;
%TEST;

マクロTESTを実行。
これにより先に登録しておいたマクロTESTの中身のプログラムが実行されます。


ちなみに、マクロの中にマクロを入れ込む事も出来ます。詳細は以下記事を参照ください。
マクロ実行文をログに展開するMPRINTとMPRINTNEST




例②

*** マクロ登録 ;
%macro TEST;
   proc print data=&DS;
   run;
%mend;

*** マクロ実行 ;
%let DS = SASHELP.CLASS;
%TEST;

%let DS = SASHELP.IRIS;
%TEST;

PRINTプロシジャでデータセットを出力するマクロTESTを登録。
「proc print data=&DS」 というように出力対象のデータセットを 「&DS」 とマクロ変数化しています。

これにより、以下のように%LETステートメントで出力するデータセットを変更しながらマクロを繰り返し実行することが出来ます。

%let DS = 出力対象のデータセット;
%TEST;






2016年5月10日火曜日

マクロ言語入門1:マクロ変数とは【%LET】



マクロの入門記事を書いていきます。まずは基本の「マクロ変数」について解説。





マクロ変数とは?


以下のプログラムを見てください。

proc print data=SASHELP.CLASS;
run;

proc means data=SASHELP.CLASS;
run;

proc contents data=SASHELP.CLASS;
run;


データセットSASHELP.CLASSに対して、PRINT, MEANS, CONTENTSプロシジャを実行しています。
ここで 「SASHELP.CLASS」 を何回も書くのが面倒なのでマクロ変数を使って以下のように書き換えてみます。

%let DS = SASHELP.CLASS ;

proc print data=&DS;
run;

proc means data=&DS;
run;

proc contents data=&DS;
run;



解説
%let DS = SASHELP.CLASS ;

「DS」という名前で定義した入れ物に「SASHELP.CLASS」という値を入れています。
この入れ物を 「マクロ変数」 と呼びます。


マクロ変数に値を設定する構文は「%LET マクロ変数 = 格納値;」となっていて、

  • このステートメントで格納値の両端に半角スペースを入れても、それらスペースはマクロ変数に含められない(別記事で解説する%STR関数を使用して含めることも可)
  • SAS側で定義している「自動マクロ変数」というものもあって、それらと同じ名前のマクロ変数を定義しないよう注意(どんな自動マクロ変数があるかはリファレンスを参照)
  • 格納値に入れると挙動が変わってしまうマクロ特有の文字(&,%等)が存在。マクロを理解するとその辺りも分かってくると思います。


proc print data=&DS;
run;

プログラム中で 「&DS」 というように&をくっつけたものはマクロ変数として解釈されます。
よって「proc print data=&DS;」は「proc print data=SASHELP.CLASS;」に置き換えて実行されます。




マクロ変数を使う利点


便利なのが、対象のデータセットをSASHELP.IRISに変えて再実行したい場合、先頭のプログラムを変えるだけで済みます。

%let DS = SASHELP.IRIS ;

proc print data=&DS;
run;

proc means data=&DS;
run;

proc contents data=&DS;
run;




マクロ変数値の確認方法


%PUT &マクロ変数名;」 でマクロ変数値をログに出力する事が出来ます。

%let DS = SASHELP.IRIS ;
%put &DS;

ログ
SASHELP.IRIS





記事一覧

1. マクロ変数とは
2. マクロの登録と実行
3. 定位置パラメータ
4. キーワードパラメータ
5. クォート処理
6. クォート処理2
7. ループ処理
8. 条件分岐処理
9. ドット
10. &&
11. 演算評価
12. 補足

2016年5月9日月曜日

マクロで 【%LET Y=%X】 みたいな書き方


あんまりやらない書き方かもしれないですが、覚えとくと役に立つと思います。


例①

%macro X;
   aaa
%mend;

%let Y = %X;

上のプログラムで、マクロ変数Yに入る値はなんでしょうか?

答え
%put &Y;

ログ
aaa

これは分かり易いと思います。


例②

%macro X;

   %local A B C;
   %let A=aaa;
   %let B=bbb;
   %let C=&A&B;

   &C

%mend;

%let Y = %X;

マクロ変数Yに入る値はなんでしょうか?

答え
%put &Y;

ログ
aaabbb

マクロ変数AとBをくっけた値「aaabbb」が返されます。
プログラム青字部分が加工フェーズ、赤字部分が展開フェーズ、みたいな構造になっています。


細かい動きは、マクロプロセッサというものを理解する必要があって、
詳しくはリファレンスを見ていただきたいのですが、

マクロ中の %LOCAL, %GLOBAL, %LET の文は、マクロプロセッサが絡むおかげで今回のような書き方が出来ると思ってください。
なので、マクロプロセッサの手中におさめられないような処理(データステップやプロシジャ等)を含めてしまうと、今回の「%let Y=%X」みたいな使用方法は出来なくなります。


この動きを理解することで、今回のような関数みたいなマクロを作ることが出来ます。


2016年5月7日土曜日

箱ひげ図をかく 【SGPLOT編】




構文

箱ひげ図の向きによってステートメントが分かれます。


縦向き
  PROC SGPLOT DATA=対象データセット;
      VBOX  分析変数 / CATEGORY=カテゴリ  オプション ;
  RUN;


横向き
  PROC SGPLOT DATA=対象データセット;
      HBOX  分析変数 / CATEGORY=カテゴリ  オプション ;
  RUN;

  • デフォルトで「CATEGORY=」を指定した軸は離散軸になりますが、ユーザー側で線形軸等に変えると、挙動が変わってしまいます。詳細はリファレンスを要確認。



オプション
  設定内容  指定   詳細設定
  箱の幅

  BOXWIDTH  =  0~1

  
  箱の書式

  FILLATTRS  =  (詳細設定) 

  COLOR = 色

  ひげの書式

  WHISKERATTRS  =  (詳細設定) 

  COLOR = 色

  中央値の書式

  MEDIANATTRS  =  (詳細設定)

  COLOR = 色

  平均値の書式 

  MEANATTRS  =  (詳細設定)
  
  COLOR   = 色
  SYMBOL = 表示マーク  

  外れ値の書式 

  OUTLIERATTRS  =  (詳細設定)   

  SYMBOL = 表示マーク 
  

…etc ( 色々できるのでリファレンスを確認してみてください )



注意
  • オプションの組み合わせで挙動が変わる可能性あり。
  • デフォルトで出力される箱ひげ図のタイプ(箱、ひげ、外れ値等の定義)はリファレンスを要確認



1. 簡単な例


title "お魚の体重分布";
proc sgplot data=SASHELP.FISH;
   vbox WEIGHT / category=SPECIES;
run;




2.カスタマイズ

title "お魚の体重分布";
proc sgplot data=SASHELP.FISH;
   hbox WEIGHT / category=SPECIES
                         boxwidth = 0.3
                         meanattrs = (color=black symbol=plus)
                         fillattrs = (color=white)
                         whiskerattrs = (color=black)
                         medianattrs = (color=black)
                         outlierattrs = (symbol=circlefilled);
run;




2016年5月2日月曜日

日付から年や月などを取り出す




日付値から 「年,月日」 を取り出す

data DT1;
  format A yymmdd10.;
  A = '05jan2014'd;
  A1 = year(A);      * 年 ;
  A2 = month(A);   * 月 ;
  A3 = day(A);        * 日 ;
run;

 A
A1
  A2   
  A3   
 2014-01-05  
  2014  
    1 
    5



日時値から 「年秒」 を取り出す


日時値から年・月・日を取り出すには、DATEPART関数で日付値に変換してからYEAR関数等を使用します

当然ながら、時・分・秒を取り出す場合は、日時のままでok (DATEPART関数は不要)

data DT2;
  format A e8601dt19.;
  A = '05jan2014 10:20:8'dt;
  A1 = year( datepart(A) );      * 年 ;
  A2 = month( datepart(A) );   * 月 ;
  A3 = day( datepart(A) );       * 日 ;
  A4 = hour(A);                      * 時 ;
  A5 = minute(A);                  * 分 ;
  A6 = second(A);                  * 秒 ;
run;

A
A1
 A2 
 A3 
 A4 
 A5  
 A6 
 2014-01-05T10:20:08 
  2014 
   1 
   5
  10 
  20
   8



1つ気をつけた方が良いのは、日時にミリ秒を含む場合。

注意:ミリ秒を含む場合

data DT3;
  format A e8601dt23.3;
  A = '05jan2014 10:20:8.721'dt;
  A1 = second(A);
run;

 A
A1
 2014-01-05T10:20:08.721 
  8.72099995・・・以下省略  

秒にミリ秒を含める場合は、「秒+(ミリ秒÷1000)」って感じになると思いますが、
SECOND関数で取得したミリ秒部分(小数点以下)に誤差?が出てしまうのでご注意ください。