公告

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

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


2007年12月25日 星期二

A Simple Way to Combine Graphs and Text - DSGI

原文載點:http://www2.sas.com/proceedings/forum2007/157-2007.pdf

在使用 SAS/GRAPH 時,有時候需要把一些特定的表格、文字或統計量整理好列在一張圖表或數張圖表旁邊。PROC GREPLAY 和 PROC GSLIDE 程序雖然有提供合併圖表的功能,但沒有辦法順便合併大量的表格和文字。Tim Tian 在 SUGI 31 發表了一篇技術文章,教使用者如何用 PROC GPRINT 程序把表格和文字轉成圖檔,然後利用 DSGI 的技術將轉檔後的圖檔與其他圖檔合併。

首先來介紹在使用 DGSI 時,如何用 gset 函示將圖檔放置位置座標進行定位。假設有四張圖表要合併成一張,如下所示:

每個圖表都有其自己的座標。使用 gset 來做定位的語法如下:
DSGI=gset('viewport', 1, 0.00, 0.51, 0.49, 1.00);
DSGI=gset('viewport', 2, 0.51, 0.51, 1.00, 1.00);
DSGI=gset('viewport', 3, 0.00, 0.00, 0.49, 0.49);
DSGI=gset('viewport', 4, 0.51, 0.00, 1.00, 0.49);

裡面有幾個參數。第一個 viewport 只是要宣告這個 gset 函數要給該圖做座標定位。第二個參數(1, 2, 3, 4)只是分配一個整數給該圖的定位,當然這些數字是不能重複的。最後四個參數就是座標。這段程式要放在一個 data step 裡面來完成,接下來就用一個實例來解說。

假設要使用 PROC GCHART 程序畫一張圓餅圖和一張 3D 直方圖。繪製這兩張圖的詳細語法在此不多做說明。唯一要注意的地方是,在程式碼中,必須使用一個叫做「name」的選項將圖表命名以作為 DSGI 進行插入圖形時所要的圖檔名稱。這個觀念有點類似在 Word 同時插入數張圖形時,必須要開啟檔案總管去尋找檔名一樣。但在 SAS/GRAPH 中,如果沒有特定的輸出語法,這些畫好的圖形都只是一個暫存檔,會隨著 SAS 關閉而消失。由於是暫存檔,所以也沒有特定檔名,因此需要額外命名讓 DSGI 能夠順利抓到想要插入的圖形。

圓餅圖程式如下:
title "Total Sale by Site";
footnote;
/* generate pie chart from TOTALS */
/* and create catalog entry PIE */
pattern1 value=solid color=cyan;
pattern2 value=solid color=green;
pattern3 value=solid color=red;
pattern4 value=solid color=yellow;
proc gchart data=totals ;
format sales dollar8.;
pie site
/ type=sum
sumvar=sales
midpoints='New York' 'Chicago' 'Atlanta' 'Seattle'
fill=solid
coutline=gray
angle=45
percent=inside
value=inside
slice=outside
noheading
name='G1';
run;

程式碼中的紅色部分即是需要替圖檔命名的重要動作。名稱可以自訂,此處使用 G1 來命名這個圓餅圖。圖形如下:

3D 立體長條圖的程式碼如下:
title1 'Total Sales by Site and Department';
footnote;
axis1 label=none origin=(24,);
axis2 label=none order=(0 to 100000 by 20000) minor=(number=1)offset=(,0);
legend1 label=none shape=bar 3,3) cborder=black cblock=gray origin=(24,);
pattern1 color=lipk; pattern2 color=cyan;
pattern3 color=lime;

goptions hpos=75 vpos=30;

proc gchart data=totals;
format sales dollar8.;
vbar3d site / sumvar=sales subgroup=dept
inside=subpct
outside=sum
width=7 space=3
maxis=axis1 raxis=axis2
cframe=gray coutline=black
legend=legend1
name='G2';
run;

同樣地,紅色部分即是將這張圖命名為 G2。圖形如下:


第三張圖其實是個純文字表格。假設是用 PROC REPORT 做出來的,程式碼如下:
filename tot 'tot.doc';
proc printto print=tot new;
run;
title;
footnote;
options linesize=64 pagesize=37 byline;
proc report data=tot2 split='\' center missing nowindows headline spacing=1;
column site dept tot;
define site / order order=data width=8 left flow "Site";
define dept / display width=13 left "Department";
define tot / display width=11 left " Sales" format= dollar11.2;
break before site/skip;
run;
proc printto;
run;

接下來的動作就是將這個純文字轉成圖檔。可用 PROC GPRINT 程序來完成。程式碼如下:
title j=l '      Summary of Sales by Site and Department';
footnote;
goptions hpos=40 vpos=28 htext=3.5 ftext=swissx;
proc gprint fileref=tot name='G3';
run;

用 PROC GPRINT 轉檔後,一樣也是要替這張圖檔命名,此處使用 G3。圖形如下所示:


上圖看起來並不是那麼好看,應該是作者在轉檔前沒有做好對齊的工作。不過無論如何,現在想要把圓餅圖和 3D 長條圖上下合併後放在一張大圖的右側,然後把轉成圖檔的表格放在左側。程式碼如下:
goptions htitle=4.5 display noborder;
title1 'XYZ Corporation Annual Earnings';
title2 'Fiscal Year 1999';
footnote;
options orientation=portrait topmargin=1 bottommargin=1 leftmargin=1 rightmargin=1;
ods listing close;
ods rtf file="&progname..rtf";
data _null_;
/* prepare SAS/GRAPH software */
/* to accept DSGI statements */
rc=ginit();
rc=graph('clear');
/* insert graph previously created ***Pie***/
rc=gset('viewport', 1, .42, 0, .90, .49);
rc=gset('window', 1, 0, 0, 100, 100);
rc=gset('transno', 1);
rc=graph('insert', 'G1');
/* insert graph previously created ***Plot***/
rc=gset('viewport', 2, .42, .51, .90, 1);
rc=gset('window', 2 0, 0, 100, 100);
rc=gset('transno', 2);
rc=graph('insert', 'G2');
/* insert text previously created ***Table***/
rc=gset('viewport', 3, 0, 0, .40, 1);
rc=gset('window', 3 0, 0, 100, 100);
rc=gset('transno', 3);
rc=graph('insert', 'G3');
/* display graph and end DSGI */
rc=graph('update');
rc=gterm();
run;
ods rtf close;
ods listing;

這段程式碼要注意的地方有幾點:
  1. gset 函示所產生的資料檔檔名可以隨便命名,此處是用 _Null_,表示 SAS 並不會真的產生這個資料檔。
  2. 除了紅色部分需要依照實際情況進行修改以外,其他部分只是單純設定的動作,可以原封不動地 copy。
  3. 每張圖都用三個 gset 設定座標(使用參數 viewport)和比例大小(使用參數 window)。至於參數 transno 只是把 viewport 和 window 所設定好的數值打包起來,而後面那個參數一定要跟之前用 viewport 和 window 所使用的第二個參數相同。最後用 graph('insert','[name]') 這個函示把 [name] 所表示的圖檔放上去。
  4. 最後用 ODS 輸出時,就會看到只有一張包含這三張小圖的大圖出現。此外,本例用一個 macro 函數 &progname 來替輸出的 RTF 檔命名。但我遍尋不著他所真正代表的名稱,研判應該前面應該有個 「%let progname=xxxxx;」,可能作者忘記放了。

最後的圖形長的像這樣:


CONTACT INFORMATION
Your comments and questions are values and encouraged. Contact the author at:
Tim Tian
Biogen Idec Inc.
14 Cambridge Center
Cambridge, MA 02142
Phone 617-679-6216
Email tim.tian@biogenidec.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; }