SAS

GTLで任意の図形を作図する DRAWステートメント

GTLでは作図する図形の座標はデータセットとして入力しますが、DRAWステートメントを使用することで座標を直接指定して作図することができます。

Drawステートメントとは

Drawステートメントはテンプレート内に直接座標を入力することで任意の場所に図形を描くことができます。anotation datasetに格納するfunctionと同等のステートメントです。
scatterplotのようなplotステートメントとは異なり、プロットエリア外にも図形を配置することができます。

任意の場所に図形を配置できるという点においては、plotステートメントの上位互換といえるでしょう。

また引数はデータセットの変数(ベクトル)ではなく数値(スカラー)のみ指定できることが特徴です。
データに依存せずに特定の図形を作図する必要があるときに使用します。

作図できる図形は以下の通りです。

ステートメント説明
drawarrow矢印を作図する
drawoval楕円または正円を作図する
drawline直線を作図する
drawrectangle四角形を作図する
drawtextテキストを挿入する
drawimage画像を挿入する
beginpolygon – endpolygon多角形を作図する
beginpolyline – endpolyline折れ線を作図する

実際に作図してみます。layoutブロックは設置せずにグラフエリアに直接図形を配置してみました。データセットは便宜上必要なのでダミーのデータを用意してsgrenderプロシジャに読み込ませます。

作図に必要な座標や大きさを直接指定することで図形を一つずつ描いていくイメージです。

proc template; 
define statgraph draw; 
begingraph; 
"Drawステートメント" / 
/*テキスト*/ 
drawtext textattrs=(color=black weight=bold size=14pt) 
   transparency=0.2 rotate=0 width=100 x=20 y=10; 

/*折れ線*/ 
beginpolyline x=30 y=85 ; 
   draw x=40 y=95; 
   draw x=50 y=85; 
   draw x=60 y=95; 
   draw x=70 y=85; 
   draw x=80 y=95; 
   draw x=90 y=85; 
endpolyline ; 

/*多角形*/ 
beginpolygon 
   x=20 y=20 / display=(fill) fillattrs=(color=pink); 
   draw x=50 y=20; 
   draw x=50 y=40; 
endpolygon; 

/*直線*/ 
drawline x1=0 y1=45 x2=100 y2=45 / lineattrs=(color=red thickness=2); 

/*楕円、height=widthの場合は正円 */ 
drawoval x=50 y=70 width=80 height=20 /display=(fill) fillattrs=(color=orange transparency=0.5) ; 

/*四角形*/ 
drawrectangle x=40 y=60 width=70 height=20 / display=(fill) fillattrs=(color=purple transparency=0.5);

 /*画像 scale=fitheightの場合は高さを元画像のアスペクト比に合うように自動調整する*/ 
drawimage "画像パス" / x=80 y=25 width=30 scale=fitheight ; 

/*矢印*/ 
drawarrow x1=20 y1=5 x2=70 y2=5 / lineattrs=(color=blue thickness=5) arrowheaddirection=both; endgraph; 
end; 
run; 

data dummy;x=.;run; 
proc sgrender data=dummy template=draw;
run;
実行結果

座標の指定方法

座標の指定方法はピクセルを直接指定する方法と基準となるブロックに対する相対位置(パーセント)で指定する方法の2つがありますが、ほぼ後者しか使わないでしょう。
基準となるブロックというのはdrawステートメントが記述されている親オブジェクトです。

例えばlayout overlayブロックに記述した場合はlayout overlayが、graphブロック内に記述した場合はgraphブロックが親オブジェクトとなります。

親オブジェクトの左下を原点として縦方向または横方向にパーセントで座標を指定します。

親オブジェクトはdrawspaceオプションで変更できます。デフォルトではlayoutブロックが親オブジェクトとして指定されます。(drawspace=layoutpercent )

drawspace=graphpercentにすると、親オブジェクトがグラフオブジェクトに設定され画像全体の任意の場所の座標を指定できるようになります。
drawspace=datavalueにすると、軸の目盛りで座標を指定できるようになります。すなわちplotステートメントと同じです。

さらに縦方向、横方向毎に基準となる親オブジェクトを指定することもできますが、まあ使うことはないでしょう。

実用性は限定的

一見任意の図形を好きな場所に配置できるので、実用性は高いように思われますが、実のところ利用できる場所がかなり限られています。

例えばdrawtextステートメントは公式では画像に透かし文字をグラフ全体に配置するコードを公開されていましたが、透かしを入れる時はたいてい
officeファイルで報告書などの成果物を作成するときです。officeソフトで作るのであれば画像ではなくofficeソフトで透かし文字を挿入するほうが後から修正がききます。

SASで透かしを入れてしまうと修正したいときにわざわざSASを立ち上げなくてはならず不便です。

またプロットエリア内に図形を挿入したいケースも限定的です。軸の範囲内であればplotステートメントで代用できますし、プロットエリア外に図形を配置する事例は
かなり少ないです。テキストを挿入する場合であってもentryステートメントとlayoutブロックを併用すれば好きな場所に文字を配置できます。

多角形や折れ線を挿入する事例も正直全く思いつきません。

特定のデータを矢印や四角形で強調表示する場合もvectorplotやpolygonplotでも作図可能です。

さらに座標の入力もピクセルか親ブロック内の相対位置というのも指定が若干面倒です。プロットエリア内であれば軸を基に目的の座標の数値を判断できますが、プロットエリア外になるとそのような基準があるわけではないため数値を決めるのは大変です。

drawステートメントはまだplotステートメントの機能が貧弱だった時代では有用でしたが、現在ではあまり憶える必要はないかなと思います。

個人的にはグラフ内に罫線を挿入する場合に限ってはdrawステートメントの方が便利かなと思います。