2016年12月27日火曜日

Graph Template Language(GTL)入門:軸の設定



GTLでX軸とY軸を設定する方法をまとめました。

ここでは「LAYOUT OVERLAY」内で軸を設定する方法を紹介します。
(LAYOUTステートメントの種類によって設定が異なる)



まず以下のように軸の場所によってオプションの名前が決まっています。





構文
PROC TEMPLATE ;
   DEFINE STATGRAPH テンプレート名;
   BEGINGRAPH ;
        LAYOUTステートメント  /  XAXISOPTS  = ( x軸オプション )
                                                    YAXISOPTS  = ( y軸オプション )
                                                    X2AXISOPTS = ( x2軸オプション )
                                                    Y2AXISOPTS = ( y2軸オプション )
                                                    WALLDISPLAY = NONE    /* 未使用の軸を消す */ ;

                    PLOTステートメント    /  XAXIS=X または X2    YAXIS=Y または Y2;     /* 使用する軸 */

        ENDLAYOUT;
   ENDGRAPH;
   END;
RUN;

PLOTステートメントで、使用する軸を設定できます(デフォルトは「XAXIS=X YAXIS=Y」)



軸オプション  (一部抜粋) 


オプションの組み合わせ・データの性質等で、挙動が変わったり、動作しないことが頻発しがちです。
リファレンスを見ながらトライ&エラーで書いていく感じになります。

設定内容設定( 以下「|」 は構文ではなく「または」の意味で記載)
軸に表示するパーツ

display = line | label | ticks | tickvalues ) | none

(複数指定可。noneの場合だけカッコで囲む必要なし。
このオプションが未指定だと全パーツが表示される)
反対側の軸表示するパーツ

displaysecondary = line | label | ticks | tickvalues )

(複数指定可)
軸ラベル

label = 'ラベル'

(ラベルの文字数が多いとデフォルトでは文字切れを起こす)
軸ラベル位置 

labelposition left | right | top | bottom

(left, rightはx,x2軸のみ、top, bottomはy,y2軸のみ指定可)
軸ラベル書式

labelattrs = (
      family = 'フォント'
      size = サイズ
      color = 
)
目盛の値の書式

tickvalueattrs=(
      family = 'フォント'
      size = サイズ
      color = 
)
グラフ内に目盛線を表示

griddisplay = on
軸を線形軸にする

type = linear
線形軸の設定linearopts (
      viewmin  = 軸の範囲(最小)
      viewmax = 軸の範囲(最大)

      tickvaluesequence = (  ※注意事項あり
                 start = 目盛開始値
                 end   = 目盛終了値
                 increment = 目盛間隔
      )

     
 tickvaluelist = (※注意事項あり  目盛値1 目盛値2 ・・・目盛値リスト )

      tickvaluepriority = true
      ・・・tickvaluelist や tickvaluesequence に指定した目盛の
                 最小・最大を軸に含める(詳細は※こちらを参照)

   
   tickvaluefitpolicy = rotate | rotatealways | stagger など
      ・・・ 目盛の文字が入りきらない時に文字の向き等を変える
             (x,x2,y,y2軸で指定できるオプションの値が異なる)

      
tickvaluerotation = vertical・・・目盛の文字を縦向きに
             (x,x2軸のみ指定可。tickvaluefitpolicyと組み合わせて使用する)
)
軸を離散値にする

type = discrete
離散値の設定discreteopts = (
      tickvaluelist = ( "目盛値1" "目盛値2" ・・・目盛値リスト )
             (注意:このオプションを設定した場合、
                指定しなかった目盛値はデータ部分もグラフから削除される)


      tickvalueformat = 目盛に当てるフォーマット

      tickvaluefitpolicy= rotate | rotatealways | stagger | extract など
      ・・・ 目盛の文字が入りきらない時に文字の向き等を変える
             (x,x2,y,y2軸で指定できるオプションの値が異なる)

 
     tickvaluerotation= vertical ・・・目盛の文字を縦向きに 
             (x,x2軸のみ指定可。tickvaluefitpolicyと組み合わせて使用する)
)



proc template ;
   define statgraph MYGRAPH;
      begingraph;
      layout overlay / walldisplay=none
                              xaxisopts=(labelposition=right griddisplay=on linearopts=(viewmin=10 viewmax=20));

        scatterplot x=AGE y=WEIGHT;
   
      endlayout;
   endgraph;
end;
run;

proc sgrender data=SASHELP.CLASS template=MYGRAPH;
run;



2016年12月19日月曜日

SASでクリスマスツリーを描画する2


去年書いた記事 「SASでクリスマスツリーを描いてみる」 を少し進化させてみました。
雪だるまと雪をunicodeで取得して、雪をチラチラさせるアニメーションを追加しました。




以下「The DO Loop」という有名なSASブログでも雪が舞い落ちるアニメーションをSASで作るプログラムを公開していて、面白いです。
「Animate snowfall in SAS」
http://blogs.sas.com/content/iml/2016/12/14/animate-snow-sas.html

今回こちらとちょっと内容被っちゃった上、私のやつの方がショボイです。。


以下が今回作ったプログラムです。一応SAS9.4で動作します。
*** ツリーとゆき描画用データ作成 ;
data SNOW;
  *** ツリー描画用データ作成 ;
  retain X1 0 Y1 1 Y2 0 Y3 -1 Y4 -2 Y5 -4;

  *** ゆき描画用データ作成 ;
  call streaminit(777);
  do scene=1 to 10;
     do X2=-3.5 to 3.5 by 0.2;
        SNOW = rand('uniform')*8-4;
        output;
     end;
  end;
run;


*** 描画 ;
title ;
options  ANIMATION=START  ANIMDURATION=0.5   PRINTERPATH=GIF ;
ods noresults;
ods printer file="出力先のパスを指定\test.gif" ;

%macro ANIMATION;
  %do i=1 %to 10;
  proc sgplot data=SNOW noautolegend;
     where scene=&i;
     styleattrs wallcolor=black;
     symbolchar name=SNOW char='2744'x;
     scatter x=X1 y=Y1 /  markerattrs=(symbol=starfilled size=0.8cm color=yellow);
     scatter x=X1 y=Y2 /  markerattrs=(symbol=trianglefilled size=1cm color=green);
     scatter x=X1 y=Y3 /  markerattrs=(symbol=trianglefilled size=2cm color=green);
     scatter x=X1 y=Y4 /  markerattrs=(symbol=trianglefilled size=3cm color=green);
     scatter x=X1 y=Y5 /  markerattrs=(symbol=squarefilled size=0.6cm color=brown);
     scatter x=X2 y=SNOW / markerattrs=(symbol=SNOW size=1.5cm color=white);
     inset "Happy Holidays(*ESC*){unicode '2603'x}"/ position=bottom textattrs=(color=white size=50cm);
     xaxis min=-3 max=3  display=none;
     yaxis min=-5 max=1  display=none;
  run;
  %end;
%mend;
%ANIMATION;

ods printer close ;
ods results;

options  ANIMATION=STOP ;


2016年12月15日木曜日

GTLで線形軸(LINEAROPTS=オプション)の最小・最大値を設定する際の注意点




よく勘違いする部分なので、まとめておきます。
ここでは「LAYOUT OVERLAY」内で線形軸を設定する場合の説明になります。



まずは軸設定の失敗例を2つ。

失敗例1
「TICKVALUESEQUENCE」や「TICKVALUELIST」で目盛を設定できますが、
たとえば以下の通り目盛「0~30」、目盛間隔「1」 と設定すると、、

proc template ;
   define statgraph MYGRAPH;
      begingraph;
      layout overlay / xaxisopts=(linearopts=(tickvaluesequence=(start=0 end=30 increment=1)));
           scatterplot x=AGE y=WEIGHT;
      endlayout;
      endgraph;
   end;
run;

proc sgrender data=SASHELP.CLASS template=MYGRAPH;
run;



実際のデータ(Age)が「11~16」の範囲にあるため、目盛は0~30ではなく、11~16になっています。


失敗例2
では今度は、目盛 「12~14」、目盛間隔「1」 と設定した場合、

proc template ;
   define statgraph MYGRAPH;
      begingraph;
      layout overlay / xaxisopts=(linearopts=(tickvaluesequence=(start=12 end=14 increment=1)));
           scatterplot x=AGE y=WEIGHT;
      endlayout;
      endgraph;
   end;
run;

proc sgrender data=SASHELP.CLASS template=MYGRAPH;
run;



実際のデータ(Age)は「11~16」なので、軸は11~16の範囲まで設けられますが、目盛としては12~14が表示されます。



よく頂く質問が、『軸の最小・最大値を 「TICKVALUESEQUENCE」や「TICKVALUELIST」で設定したのに、うまく設定できない!』というものです。
上記で説明した通り、 「TICKVALUESEQUENCE」や「TICKVALUELIST」は目盛を設定するだけなので、軸の範囲(最小・最大)も別途設定する必要があります。



以下に軸の設定例を2つ紹介します。
【シチュエーション】軸の最小・最大を0~30、目盛間隔を2に設定したい


軸の設定例1
「TICKVALUEPRIORITY=TRUE」を指定することで、「TICKVALUESEQUENCE」や「TICKVALUELIST」による目盛の最小・最大値を軸に含めることが出来ます。

proc template ;
   define statgraph MYGRAPH;
      begingraph;
      layout overlay / xaxisopts=(linearopts=(tickvaluepriority=true
                                                               tickvaluesequence=(start=0 end=30 increment=2)));
           scatterplot x=AGE y=WEIGHT;
      endlayout;
      endgraph;
   end;
run;

proc sgrender data=SASHELP.CLASS template=MYGRAPH;
run;

ただし「失敗例2」のように、
「TICKVALUESEQUENCE」や「TICKVALUELIST」で設定した目盛の範囲外に、実際のPLOTするデータがある場合、「TICKVALUEPRIORITY=TRUE」は効果なしです(結果は「失敗例2」の出力結果と同様、実際のPLOTするデータの範囲まで軸が拡張される)



軸の設定例2
「VIEWMIN」,「VIEWMAX」で軸の範囲(最小・最大)を設定し、「TICKVALUESEQUENCE」や「TICKVALUELIST」で目盛を設定する。

proc template ;
   define statgraph MYGRAPH;
      begingraph;
      layout overlay / xaxisopts=(linearopts=(viewmin=0 viewmax=30
                                                               tickvaluesequence=(start=0 end=30 increment=2)));
           scatterplot x=AGE y=WEIGHT;
      endlayout;
      endgraph;
   end;
run;

proc sgrender data=SASHELP.CLASS template=MYGRAPH;
run;

注意点として、
「VIEWMIN」「VIEWMAX」で軸の範囲(最小・最大)が固定されるので、実際のPLOTするデータが軸の範囲外にあっても、その範囲外のPLOT部分はグラフに表示されません。


最後に、
他のオプションとの組み合わせによって、今回紹介したオプションの機能が無効または挙動が変わるので、その辺りの細かい部分についてはリファレンスも確認してみて下さい。



2016年12月10日土曜日

SASデータセットを削除するDELETEプロシジャ



SAS9.4から正式に使えるようになったDELETEプロシジャを紹介します。

以前のバージョンでも、マニュアルに載ってないけど実は使えるっていう、知る人ぞ知るプロシジャでした。
正式に認めてもらえるまで大分時間がかかったけど、やっと表舞台に立てて感無量ですね。

このプロシジャでSASデータセットを削除することが出来ます。



以下、SASデータセットを削除する例をいくつか見ていきましょう。


* サンプルデータ作成 ;
data DT1 DT2 DT3 DT4 DT5 DT6 DT7 DT8;
run;


* ① WORKライブラリの DT1 と DT2 を削除 ;
proc delete lib=WORK data=DT1 DT2;
run;

* ② WORKライブラリの DT3~DT5 を削除 ;
proc delete lib=WORK data=DT3-DT5;
run;

* ③ WORK.DT6 を削除 ;
proc delete data=WORK.DT6;
run;

* ④ WORKライブラリの全データセットを削除 ;
proc delete data=WORK._ALL_;
run;

①と②はSAS9.4から可能になった書き方です。


データセット以外のSASファイルを削除する場合は「MEMTYPE=」で削除するデータのタイプを指定します。例えば、以下 DT20, DT21 というVIEWがあったとして、、


data DT20 / view=DT20;
run;
data DT21 / view=DT21;
run;


以下のように書いて削除します。

proc delete lib=WORK data=DT20 DT21 (memtype=view);
run;


ちなみに1回のPROC DELETEで削除できるデータのタイプは1種類のみで、「VIEWとデータセットをいっぺんに削除」みたいな事は出来ませんでした。



注意点

  • 存在しないデータセットを削除しようとするとログにWARNINGが出力されます。
  • 世代データセットや、外部キーを設定したデータセットなど、特殊なデータセットを削除する際の挙動についてはリファレンスをご確認下さい。