公告

[公告]
2014/01/17
由於已經是faculty的關係,不太有足夠時間寫部落格。因此更新的速度會相當緩慢。再加上近幾年來SAS GLOBAL FORUM沒有出現讓我覺得驚艷的技術文件,所以能分享的文章相對也減少許多。若有人推薦值得分享的SAS技術文件,請利用『問題討論區』告知。

2013/07/19
臉書留言板的功能因為有不明原因故障,因此特此移除。而intensedebate的留言板因管理不易,也一併移除。目前已經開啟內建的 G+ 留言系統,所以請有需要留言的朋友,可直接至『問題討論區』裡面留言。


2007年7月24日 星期二

How to annotate graphics

原文載點:http://www.lexjansen.com/phuse/2006/tu/tu05.pdf

[註] 本文於 2008/01/03 做局部修訂。主要是解決程式區中出現亂碼的問題。

我曾經在 SAS/GRAPH 101 這篇部落格文章裡面提到一點簡單的 annotate 用法。根據個人以往的經驗,這一部份是很難從學校的統套課程中學到(我也很懷疑有幾個老師會),大都需要靠自修。偏偏 annotate 是想要繪製更精密圖形必經之路,但他又不是那麼好學,所以要能夠靈活運用 annotate 語法可真的不是一件簡單的事情。因此,我一直在想,難道沒有人能夠弄些 macro 程式來簡化 annotate 嗎?很巧的是,當這個念頭才剛閃過,我就在 PhUSE 2006 內的最後一篇文章看到一個法國人 Sandrine Stepien 發表的 annotate macro 教學技術文件,才知道原來 SAS 內部本來就已經有 annotate macro 可以直接使用(連呼叫都不用)。希望這篇文章能讓想要學 annotate 的人能夠省下一點時間。

annotate 變數大致可以分成四類:
  • 動作變數(action variable):告訴 SAS 該做什麼動作(移動、繪圖、描點 ... etc)
  • 系統變數(system variable):設定座標軸系統
  • 位置變數(position variable):告訴 SAS 在哪裡做那些動作(X 軸或 Y 軸 ... etc)
  • 屬性變數(attribute variable):告訴 SAS 該設定哪些繪圖屬性(顏色,大小 ... etc)
我跳過關於這些變數的介紹,直接切入 annotate macro 的主題。annotate macro 主要有下面幾個:
  • %TXT2CNTL; -- 將 (XLSTT, YLSTT) 的值分派到 (XLAST, YLAST)
  • %POLY(x, y, color, style, line); -- 開始畫一個多邊形
  • %POLYCONT(x, y, color); -- 繼續畫一個多邊形
  • %CNTL2TXT; 將 (XLAST, YLAST) 的值複製到 (XLSTT, YLSTT)
  • %DCLANNO; -- 宣告所有變數
  • %BAR(x1, y1, x2, y2, color, line, style); -- 畫長條圖
  • %CIRCLE(x, y, size, color); -- 畫圓
  • %FRAME(color, line, size, style); -- 畫外框
  • %DRAW2TXT(color, line, size); -- 畫線(從(XLAST, YLAST) 到 (XLSTT, YLSTT))
  • %DRAW(x, y, color, line, size); -- 畫線(從前一個點畫到(x,y))
  • %LINE(x1, y1, x2, y2, color, line, size); -- 畫線(從(x1,y1)畫到(x2,y2))
  • %SLICE(x, y, angle, rotate, size, color, style, line); -- 畫扇形圖
  • %RECT(x1, y1, x2, y2, color, line, size); -- 畫長方形
  • %LABEL(x, y, text, color, angle, rotate, size, style, position); -- 寫字
  • %SWAP; -- 交換 (XLAST, YLAST) 和 (XLSTT, YLSTT) 的值
  • %PIEXY(angle, size); -- 把一個點放在之前畫好的扇形圖旁
  • %MOVE(x, y); -- 在沒有進行繪圖的情況下移動一個點到 (x,y)
  • %PUSH; -- 將數值丟進 LIFO
  • %POP; -- 從 LIFO 取得數值
  • %SCALET(ptx, pty, x0, y0, x1, y1, vx0, vy0, vx1, vy1); -- 設定比例尺並自動控制原始位置
  • %SCALE(ptx, pty, x0, y0, x1, y1, vx0, vy0, vx1, vy1); -- 設定比例尺
  • %SYSTEM(xsys, ysys, hsys); -- 設定系統變數 xsys, ysys 和 hsys(若畫 2D 圖可省略 hsys 的設定)
  • %SEQUENCE(when);-- 定義 annotate 開始作用在繪製某個物件之前或之後。when 可填入 before 或 after。
  • %COMMENT(text); -- 在資料檔裡面加上註解
其中,XLAST 和 YLAST 是定義非文字型的座標軸,而 XLSTT 和 YLSTT 是定義文字型的座標軸。

想要看原文解釋的人可以在 SAS 內執行下面這個 macro 來查詢:

%HELPANO(ALL);

另外得記住,要執行 annotate macro 時,一定要先執行 %annomac; 才能啟動所有的 annotate macro。

以下介紹一個例子來展現 annotate macro 的威力。

如果想要做出下面這樣子的圖形:



得執行這道程式:

data mean;
input trt time dbp sem n;
cards;
1 0.5 88 4 10
1 1 89 6 9
1 2 87 4 12
1 3 88 7 10
1 4 86 5 10
1 6 84 6 11
1 8 83 8 15
1 10 80 4 8
1 12 83 5 8
2 0.5 81 3 13
2 1 82 7 10
2 2 80 5 11
2 3 80 7 12
2 4 78 5 13
2 6 82 4 10
2 8 80 8 10
2 10 79 6 9
2 12 76 4 8
;
run;
proc sql noprint;
select min(dbp-sem-5) into:minval from mean;
select max(dbp+sem+5) into:maxval from mean;
quit;

%annomac;
data ANNO1;

length function style color $8 text $50;

set mean;

tiret='_';
%annomac;

%system(2,2); *--color--*;
if trt=1 then do;

%line(time+0.1,dbp-sem,time+0.1,dbp+sem,olive,2,2);
%label(time+0.1,dbp-sem,tiret,olive,0,0,1,simplex,B);

%label(time+0.1,dbp+sem,tiret,olive,0,0,1,simplex,B);

end;

if trt=2 then do;
%line(time,dbp-sem,time,dbp+sem,gold,1,2);
%label(time,dbp-sem,tiret,gold,0,0,1,simplex,B);

%label(time,dbp+sem,tiret,gold,0,0,1,simplex,B);
end;

run;
proc format;
value TRT 1='Treatment X'
2='Treatment Y';
run;

goptions reset=all
display
cback=white
ftext=simplex
ftitle=swiss
colors=(black)
gunit=pct
ctext=black
htext=3
htitle=2;
axis1 offset=(5,5) label=(h=3 j=r "time point (hours)" ) value=(h=3);
axis2 offset=(2,2) label=(h=4 angle=90 "Diastolic blood Pressure (mmHg)") value=(h=3) order=(&minval to &maxval by 10);
legend1 label=(h=3 'treatement:') position=(top center inside) mode=protect value=(h=3 j=left) across=1;
symbol1 i=join value=none line=2 color=olive width=4 h=2;
symbol2 i=join value=none line=1 color=gold width=4 h=2;
title;footnote;
title1 j=c h=4 "Figure X: Annotated plot of mean";
proc gplot data=mean gout=graf;
plot DBP*time=trt/ vaxis=axis2 haxis=axis1 legend=legend1 annotate=ANNO1;
format trt trt.;
run;
quit;

這個程式主要可分為三部分:
一、資料輸入(data step)和敘述統計量輸出(proc sql,也可用 proc means)。
二、用 annotate macro 來產生 annotate data。
三、正規繪圖流程(proc gplot)。

第一和第三部分已經在之前的教學文章裡面談到很多次,所以這回只針對第二部分的 annotate macro(即程式中紅色部分)來解說。

步驟一:先執行一次 %annomac。
步驟二:建立一個名為 ANNO1 的 annotate data。
步驟三:設定動作變數(function)和屬性變數(style、color、text)的長度。
步驟四:把剛剛 proc sql 做出來的敘述統計量資料(mean)給呼叫進來。
步驟五:再執行一次 %annomac。
步驟六:執行系統變數 annotate macro(%system(2,2))。這個 macro 是一次設定 xsys 和 ysys 這兩個系統變數。至於裡面的數字所代表的意思,請見下圖:



步驟七:繪製特定的線和圖例(用 %line 和 %label 這兩個 annotate macro)
步驟八:最後,不要忘了,記得在 PROC GPLOT 的 plot statement 後面加上 annotate=ANNO1,如此一來這些設定才會套進 PROC GPLOT 所畫的圖裡面。

文件內還有其他例子,但大體上是大同小異。有興趣的人可以自行下載原文來看。

CONTACT INFORMATION
Your comments and questions are valued and encouraged. Contact the author at:
Sandrine STEPIEN
QUINTILES
4 route de la rivière
67380 LINGOLSHEIM
Phone: +33(0)3 88 77 44 13
Email: Sandrine.stepien@quintiles.com

沒有留言:

張貼留言

要問問題的人請在文章下方的intensedebate欄位留言,請勿使用blogger預設的意見表單。今後用blogger意見表單留言的人我就不回應了。

CODE { display: block; /* fixes a strange ie margin bug */ font-family: Courier New; font-size: 8pt; overflow:auto; background: #f0f0f0 url(http://klcintw.images.googlepages.com/Code_BG.gif) left top repeat-y; border: 1px solid #ccc; padding: 10px 10px 10px 21px; max-height:200px; height:200px; // for IE6 line-height: 1.2em; }