2008年12月26日 星期五

Easy as Pie Charts

原文出處:http://www2.sas.com/proceedings/forum2008/071-2008.pdf




此文主要是用在圓餅圖的美化
一開始的圓餅圖畫法如下
Example 1
1.2D圓餅圖

goptions device=gif gsfname=chart hpos=100 vpos=100 htext=2
ftext=zapfb ;
data example1 ;
input dessert $3. ;
datalines ;
Pie
;
run ;
proc gchart data=example1 ;
title "Example 1a: Pie Hole Thin" ;
pie dessert / noheading
slice=none value=none ;
footnote "You always win with a Pie Hole Thin!" ;
run ;
quit ;


2.3D圓餅圖

goptions device=gif gsfname=chart hpos=100 vpos=100
htext=2 ftext=zapfb ;
data example1 ;
input dessert $3. ;
datalines ;
Pie
;
run ;
proc gchart data=example1 ;
title "Example 1b: Pie Hole Thick" ;
pie3d dessert / noheading
slice=none value=none ;
footnote "The greatest pick is a Pie Hole Thick! (50% more filling)" ;
run ;
quit ;


3.甜甜圈型圓餅圖

goptions device=gif gsfname=chart hpos=100 vpos=100
htext=2 ftext=zapfb ;
data example1 ;
input dessert $3. ;
datalines ;
Pie
;
run ;
proc gchart data=example1 ;
title "Example 1c: Pie Hole Trim" ;
donut dessert / noheading
slice=none value=none label=("50% less filling")
donutpct=50 ;
footnote "Stay slim with a Pie Hole Trim!" ;
run ;
quit ;


上述三種圓餅圖語法僅差在是否宣告為pie, pie3d, 或是donut.
三種圖如下





不過上述語法仍有一些圖形化的修飾語法,如noheading slice=none value=none ,其中noheading與圖型比例資料類型的子標題有關,如不宣告則圓餅圖上方會出現該圖形的子標題"frequency of dessert";slice為分組變相的標籤位置,可將none改為inside或outsinde;value為計算變項的結果位置,可將none改為inside或是outside.下面則進一步說明如何利用這些宣告來繪製圓餅圖.




Example 2

如下語法為例(以2D圓餅圖作說明)

goptions device=gif gsfname=chart hpos=100 vpos=100
htext=2 ftext=zapfb ;
proc format ;
value example2a 1="$1.99" 2="$2.99" 3="$3.99" 6="$6.99" ;
value example2b 1="$3.99" 2="$5.99" 3="$7.99" 6="$13.99" ;
value example2c 1="$0.99" 2="$1.49" 3="$1.99" 6="$3.49" ;
run ;
data example2 ;
input size $ portion ;
datalines ;
Small 1
Medium 2
Large 3
X-Large 6
;
run ;
proc gchart data=example2 ;
title "Example 2a: Pie Hole Thin Slices" ;
pie size / sumvar=portion noheading
slice=inside value=inside
;
format portion example2a. ;
footnote "Get a whole Pie Hole Thin for just $12.99!" ;
run ;
quit ;



在pie後所宣告的變項size如同proc means使用class的用途,將該變項各類型定義,並且在
sumvar=宣告計算的變項或是比例,也可用freq= ,但兩者仍有不同,一個是值一個是次數

slice=是指size宣告內各分組標籤位置(可改為none,outside,inside, arrow)

value=是指sumvar計算後之值的位置(可改為none,outside,inside)

結果如下圖


而3D 與 甜甜圈圓餅圖 結果與上述相同

goptions device=gif gsfname=chart hpos=100 vpos=100 htext=2 ftext=zapfb ;
proc format ;
value example2a 1="$1.99" 2="$2.99" 3="$3.99" 6="$6.99" ;
value example2b 1="$3.99" 2="$5.99" 3="$7.99" 6="$13.99" ;
value example2c 1="$0.99" 2="$1.49" 3="$1.99" 6="$3.49" ;
run ;
data example2 ;
input size $ portion ;
datalines ;
Small 1
Medium 2
Large 3
X-Large 6
;
run ;
proc gchart data=example2 ;
title "Example 2b: Pie Hole Thick Slices" ;
pie3d size / sumvar=portion noheading slice=inside value=inside ;
format portion example2b. ;
footnote "Get a whole Pie Hole Thick for just $25.99!" ;
run ;
quit ;
proc gchart data=example2 ;
title "Example 2c: Pie Hole Trim Slices" ;
donut size / sumvar=portion noheading slice=inside
value=inside
donutpct=50 ;
format portion example2c. ;
footnote "Get a whole Pie Hole Trim for just $6.49!" ;
run ;
quit ;


甜甜圈圓餅圖中donutpct=50 , 是說明甜甜圈中間那個"洞"的大小




Example 3

接著進一步說明如何將圓餅圖作切分
語法如下

goptions device=gif gsfname=chart hpos=100 vpos=100
htext=2 ftext=zapfb ;
data example3 ;
input flavor & $15. sales ;
datalines ;
Apple 6127
Banana Cream 911
Blueberry 875
Cherry 4592
French Silk 1106
Key Lime 1869
Lemon Meringue 1227
Peach 1322
Pecan 1870
Pumpkin 2991
Rhubarb 1794
Sweet Potato 997
;
run ;
proc gchart data=example3 ;
title "Example 3: Most Frequently Purchased Pies" ;
pie flavor / sumvar=sales noheading slice=inside
value=none percent=inside
fill=solid cfill=STYBR other=5 otherlabel="All Others"
;
footnote "The 'All Others' slice contains pies purchased < 5% of the time" ;
run ;
quit ;


其中的percent=是顯示圓餅圖被切分的百分比並顯示其位置(none, inside, outside)
fill=為選擇圖層填滿之效果(solid, x, empty),一般可以不用宣告
cfill=為圖層填滿之效果,可參考SAS patterns的說明,或是直接打上自己想要的顏色如(red, green, black, cyan),一般可以不用宣告,引用預設值

other=5則是挑選後百分之5作為其他群組,可以自行改為其他百分比
otherlabel="All Others" 則是將挑選出來的增加標籤"All Others"

結果如下圖


若想要把圓餅圖內的顏色作層次,其實可以修改一下語法

在goptions內 加入 colors=(red green .... 等)
或是利用pattern語法宣告顏色

語法如下

goptions device=gif gsfname=chart hpos=100 vpos=100 htext=2
ftext=zapfb colors=(black blue green gray lipk) ;


data example3 ;
input flavor $15. sales ;
datalines ;
Apple 6127
Banana Cream 911
Blueberry 875
Cherry 4592
French Silk 1106
Key Lime 1869
Lemon Meringue 1227
Peach 1322
Pecan 1870
Pumpkin 2991
Rhubarb 1794
Sweet Potato 997
;
run ;


filename chart "C:\My Documents\Graphs\example3.gif" ;

pattern1 color=black;
pattern2 color=blue;
pattern3 color=green;
pattern4 color=gray;
pattern5 color=lipk;
pattern6 color=lime;
pattern7 color=cyan;
pattern8 color=red;

proc gchart data=example3 ;
title "Example 3: Most Frequently Purchased Pies" ;
pie flavor / sumvar=sales noheading slice=inside value=none
percent=inside
other=3 otherlabel="All Others" ;
footnote "The 'All Others' slice contains pies purchased < 5% of the time" ;
run ;
quit ;


其結果如下圖





Example 4
當資料有分組時,以下方式就是將分組之圓餅圖同時顯示

goptions device=gif gsfname=chart hpos=100 vpos=100
htext=2 ftext=zapfb ;
data example4 ;
input season flavor $ sales ;
cards ;
1 a 100
1 b 200
1 c 300
1 d 400
1 e 500
2 a 500
2 b 400
2 c 300
2 d 200
2 e 100
3 a 200
3 b 200
3 c 200
3 d 200
3 e 200
4 a 100
4 b 200
4 c 300
4 d 200
4 e 100
;
run ;
proc gchart data=example4 ;
title "Example 4: Most Frequently Purchased Pies by Season" ;
pie flavor / sumvar=sales noheading slice=inside
value=none percent=inside
fill=solid cfill=STYBR other=5 otherlabel="All Others"
group=season
across=3 down=2
;
footnote "The 'All Others' slice contains pies purchased < 5% of the time" ;
run ;
quit ;


group=是宣告即將分組之變項seasin
across=則是宣告圖堆疊時橫向放幾個組
down=則是宣告圖堆疊時縱向放幾個組
即此結果為2*2的圖形如下





Example 5

若對於圓餅圖想要做出凸顯或隱藏的區塊時如缺角圓餅圖(3D圓餅圖也能直接使用)
以下語法是將某區塊做隱藏


goptions device=gif gsfname=chart hpos=100 vpos=100
htext=2 ftext=zapfb ;
proc format ;
picture example5_ low-high="999 Votes" ;
run ;
data example5 ;
input flavor $15. votes ;
cards;
Blackberry 648
Cranberry 377
Mixed Berry 393
Mud 341
Strawberry 479
Sugar 432
;

proc gchart data=example5 ;
title "Example 5a: The New Customer-Voted Pie is...?" ;
pie flavor / sumvar=votes noheading slice=inside value=outside
percent=outside cfill=Y
ascending angle=10 invisible="Blackberry" ;
format votes example5_. ;
footnote "The new pie will be revealed on Friday at noon!" ;
run ;
quit ;


ascending的宣告是指資料在圖型時的排列
angle=為角度的旋轉
invisible=為想要隱藏的區塊

結果如下圖


然而消失的區塊"Blackberry"若是想要突顯的
則上述語法可以將invisible=替換成
explode=
結果如下圖






Example 6

若想要更進一步排版圓餅圖輸出時
以下語法

goptions device=gif gsfname=chart hpos=100 vpos=100
htext=2 ftext=zapfb ;
data example6 ;
input flavor $15. calories ;
cards;
Apple 255
Banana Cream 505
Blueberry 380
Cherry 450
French Silk 680
Key Lime 365
Lemon Meringue 355
Peach 425
Pecan 625
Pumpkin 280
Rhubarb 375
Sweet Potato 325
;

proc gchart data=example6 ;
title "Example 6: Calories per Slice" ;
pie flavor / sumvar=calories noheading
slice=arrow value=inside ascending
clockwise coutline=BL ;
pattern1 color=CX990000 ;
pattern2 color=CXFFFF99 ;
pattern3 color=CX3333CC ;
pattern4 color=CXCC0000 ;
pattern5 color=CX663300 ;
pattern6 color=CX00CC66 ;
pattern7 color=CXFFFF33 ;
pattern8 color=CXFF9966 ;
pattern9 color=CX996633 ;
pattern10 color=CXFF9900 ;
pattern11 color=CXCC0066 ;
pattern12 color=CXFFCC66 ;
footnote "These numbers are based on a small slice of a Pie Hole Thin" ;
run ;
quit ;


先前有提到slice=是變項資料的標籤位置,
若改為arrow則會拉線出來指示位置

clockwise 是指排列時呈現順時針或逆時針方向

cutline=則是圓餅圖邊框,可打顏色名稱如red , green 等

結果如下圖






Example 7

若對於圓餅圖上的色塊增加圖層說明時(legend),常用GIS的地圖輸出時看到
其方法如下

goptions device=gif gsfname=chart hpos=100 vpos=100
htext=2 ftext=zapfb ;
data example7 ;
input flavor $15. calories ;
cards;
Apple 255
Banana Cream 505
Blueberry 380
Cherry 450
French Silk 680
Key Lime 365
Lemon Meringue 355
Peach 425
Pecan 625
Pumpkin 280
Rhubarb 375
Sweet Potato 325
;
run ;
proc gchart data=example7 ;
title "Example 7: Calories per Slice" ;
pie flavor / sumvar=calories noheading slice=none
value=inside ascending
clockwise coutline=BL legend=legend1 ;

legend1
label=none
position=(left middle)
offset=(2 , 4 )
across=1
shape=bar(4, 4)
cblock=MEGR
cborder=DAGR
cframe=LIGR
order=("Apple" "Pumpkin" "Sweet Potato" "Lemon Meringue"
"Key Lime" "Rhubarb" "Blueberry" "Peach" "Cherry" "Banana
Cream" "Pecan" "French Silk")
;

pattern1 color=CX990000 ;
pattern2 color=CXFFFF99 ;
pattern3 color=CX3333CC ;
pattern4 color=CXCC0000 ;
pattern5 color=CX663300 ;
pattern6 color=CX00CC66 ;
pattern7 color=CXFFFF33 ;
pattern8 color=CXFF9966 ;
pattern9 color=CX996633 ;
pattern10 color=CXFF9900 ;
pattern11 color=CXCC0066 ;
pattern12 color=CXFFCC66 ;
footnote "These numbers are based on a small slice of a Pie Hole Thin" ;
run ;
quit ;



上述中須宣告legend=legend1 的使用
並宣告legend1的特性

label=none 是指說明層加入標題如改為label=("flavor")

position=(left middle)則是排定說明層所在位置
(BOTTOM,MIDDLE,TOP,LEFT,CENTER,RIGHT,OUTSIDE,INSIDE)

offset=(2 , 4 )指說明層偏移距離並可附上位移單位如
offset=(2 pct , 4 pct)

across=1是指說明層內左右納入幾欄資料層

shape=bar(4, 4)是指說明層的色塊說明類型及大小(寬*高)

cblock=MEGR是指說明層邊緣陰影顏色(red, blue 等)
cborder=DAGR是指說明層邊框顏色
cframe=LIGR是指說明層底色
也可以加上CSHADOW=black美化邊框,這些功能有如word內畫圖工具

order=()是指說明層列出變項資料欄的順序
上述這些美化宣告可以任意組合及使用

結果如下圖






Example 8

若有雙層型態時語法如下

goptions device=gif gsfname=chart hpos=100 vpos=100
htext=2 ftext=zapfb ;
data example8 ;
input gender $ style $ orders ;
datalines ;
Male Thin 366
Male Thick 531
Male Trim 103
Female Thin 512
Female Thick 181
Female Trim 307
;
run ;

proc gchart data=example8 ;
title "Example 8: Pie Selection by Gender" ;
pie style / sumvar=orders noheading slice=none
value=outside
percent=outside coutline=BL matchcolor
legend=legend1
detail=gender detail_slice=best detail_value=none
detail_percent=best detail_threshold=0 detail_radius=85 ;


legend1 label=none position=(bottom center)
offset=(0, 4) across=3
shape=bar(4, 2) cblock=MEGR
cborder=DAGR cframe=LIGR ;
pattern1 color=ROSE ;
pattern2 color=OLIVE ;
pattern3 color=LIGB ;
footnote "The first 1000 orders from each gender were counted" ;
run ;
quit ;


matchcolor是指slice的標籤融入背景顏色中
detail=gender是指第二層級的分組
detail_slice=best指第二層級資料標籤(best,none)
detail_value=none第二層級資料(best,none)
detail_percent=best第二層級資料百分比(best,none)
detail_threshold=0第二層級界限百分比(0-75),
如detail_threshold=10,則第一層級低於百分值10會被融入背景中
detail_radius=85第二層圓框面積的縮放百分比(25-90)

結果如下圖



proc gchart

Easy as Pie Charts

2008年12月9日 星期二

利用ODS抓取報表上的結果

一般使用SAS都是先經過proc程序所提供的統計計算去獲得結果並且進一步去轉出該結果的資料。然而當有結果是在報表上的某一個值時,例如利用迴圈的方式想要獲得多組AIC值時,或是參數估計報表內的係數轉換如poisson regression係數轉換為RR值等
如下圖紅框處是我想要擷取的報表


然而很多程序未能支援輸出(output)類似係數估計的報表

固然需要利用其他語法來彌補這樣的問題

如下為人口統計中計算相對危險性所會用到的語法

proc genmod data= deathPoisson;
model _COL10 =class1 class2 class3 class4 class5 / link=log dist=poisson offset=logP lrci;
run;

然而我們僅能在SAS求出Poisson迴歸係數如上圖
但我們會希望能夠求出RR以及信賴區間等資料

可以利用ODS的語法將該係數報表轉換出來,其語法如下


ODS trace on;

proc genmod data= deathPoisson;
model _COL10 =class1 class2 class3 class4 class5 / link=log dist=poisson offset=logP lrci;
run;

ODS trace off;


上述語法中以 ODS trace on; 為開頭, ODS trace off; 為結尾將欲轉出的報表語法包起來
此時先做執行運算動作,並且到log視窗去
會看到如下報表


此為各結果報表的內定值,若對欲特定報表想要轉出時找出該報表對應名稱(Label)

例如欲取出Analysis Of Parameter Estimates這張報表的係數加以換算為RR時在語法中其對應的檔案為ParameterEstimates


找出該張報表的語法後
再把原來的語法改為如下

ods output ParameterEstimates = classparameter;
proc genmod data= deathPoisson;
model _COL10 =class1 class2 class3 class4 class5 / link=log dist=poisson offset=logP lrci;
run;
data CIclass;
set classparameter ;
RR=exp(Estimate);
RRL95=exp(LowerLRCL);
RRU95=exp(UpperLRCL);
proc print data=CIclass;
var Parameter RR RRL95 RRU95;
run;

增加ods output ParameterEstimates = classparameter;宣告即為轉出該結果的係數資料,classparameter則是新取名的檔案名稱
其結果如下圖將轉出的係數再計算其自然數e,即為RR值



2008年6月10日 星期二

Infile

The SAS INFILE and FILE Statements

The SAS INFILE and FILE Statements

原文出處:http://www2.sas.com/proceedings/forum2008/166-2008.pdf


proc report

Learning PROC REPORT by Comparison

Learning PROC REPORT by Comparison

原文出處:
http://www2.sas.com/proceedings/forum2008/170-2008.pdf




此文是以學習proc report並且比較與該程序有相似的程序如proc print, proc tabulate及proc means等



1.與proc print比較
當有資料欲做初步的顯示時通常可利用print的動作將資料秀出,而proc report則也能做相同的動作
如下為proc print的範例(資料來自主程式內的範例,可直接使用)

title 'Simeple Listing' ;
proc print data=sashelp.class ;
var name sex age height weight ;
title2 'PROC PRINT' ;
run ;



結果如下圖

其中的資料各變項僅需在proc print的附屬語法var後面打上欲呈現的變項即可

而在proc report部分語法如下

proc report data=sashelp.class nowd headskip ;
column name sex age height weight ;
define sex / width=3 ;
title2 'PROC REPORT' ; run ;



其中proc report後方的附屬語法:

nowd可以抑制該程序不產生獨立的報告視窗,其效果有如proc print一樣皆將結果輸出在output視窗上,然而獨立的報告視窗有其好處,例如可及時更改該變項顏色或屬性,方便報表輸出的可讀性.

headskip則是修飾報表中變項欄位與第一觀察值的距離

語法中column則與proc print中var效果相同,一樣是宣告欲呈現的變項語法

define則為定義某變項的資料屬性例如後面加上 sex /width=3 ,則宣告sex變項長度為3

根據上述proc report語法,其結果如下,會與proc print輸出報表相似



若常用 proc print功能的人眼尖的話因該會發現print報表其實有個預設值OBS(觀察值序號)
如下圖

而proc print可透過語法將此觀察值序號開啟或關閉,方法如下(只要打上noobs即可關閉)

title 'Simeple Listing' ;
proc print data=sashelp.class noobs ;
var name sex age height weight ;
title2 'PROC PRINT' ;
run ;



然而proc report其實沒有直接提供觀察值序號的功能,
不過可以透過語法的撰寫來達到相似的功能
proc report語法如下

proc report data=sashelp.class nowd headskip ;
column Obs name sex age height weight ;
define sex / width=3 center ;
define age / width=5 ;
define height / format=6.1 ;
define weight / format=6.1 ;
define obs / computed ;
compute obs ;
count+1 ;
obs=count ;
endcomp ;

title2 'PROC REPORT, again' ;
run ;


上述語法中,先在colume後先建立一空變項Obs
接著再宣告Obs格式並利用computed再處理該變項特性值
結果如下圖,會與proc print相似





2.配合sorted listing功能

當資料利用proc print程序列出時,欲先將性別sex變項作排序,其語法如下

proc sort data=sashelp.class out=class ;
by sex ;
run ;
title 'Sorted Listing' ;
proc print data=class ;
var name age ;
by sex ;
id sex ;
title2 'PROC PRINT' ;
run ;

其結果如下



而proc report程序也是能做到上述排序資料的功能,語法如下只要在define後面加個order宣告

proc report data=sashelp.class nowd headskip ;
column sex name age ;
define sex / order width=3 ;
break after sex / skip ;
title2 'PROC REPORT' ;
run ;

其結果如proc print相似如下


而在語法中用到 break after sex / skip ;
則是將報表作斷行的動作,也可將after改為before,
其目的可在後續作資料加總時修改報表板面



3.列出排序後子項的總合
利用proc print加入sumby sex語法,即能表現出sex變項排序後子項目的加總


proc print data=class ;
var name age ;
by sex ;
id sex ;
sumby sex ;
title2 'PROC PRINT' ;
run ;

其結果如下紅框處



而若利用proc report語法呈現如上述的結果報表時,需要有一些宣告

proc report data=sashelp.class nowd ;
column sex name age ;
define sex / order width=3 ;
define age / analysis sum format=4.;
break before sex / skip ;
break after sex / summarize ol ;
rbreak after / summarize dol ;

title2 'PROC REPORT' ;
run ;



其中analysis sum是宣告age變項是可分析可加總

break before sex / skip ;則為依照sex變項作斷行break,斷行的方式為向前(before)斷行並空格(skip),若將skip改為page則斷行會跳頁

break after sex / summarize ol;則是宣告在sex變項斷行後作加總(summarize)的動作並且給予上標單槓符號(ol)----方便報表閱讀

rbreak after / summarize dol ;則是指變項最後斷行的處理(rbreak),將變項做總加總(summarize)的動作,並且給予上標雙槓符號(dol)====

結果如下圖

註:上標符號可改為下標如:ul dul,並且可在獨立視窗時(未宣告nodw時)打上color=顏色(red)

接下來的語法是將上述作一些美化的動作,語法如下

proc report data=sashelp.class nowd ;
column sex sex2 name age ;
define sex / order width=3 noprint ;
define sex2 / computed 'Sex' ;
define age / mean format=best4. ;
break before sex / skip ;
break after sex / summarize ol ;
rbreak after / summarize dol ;
compute sex2 / character length=15 ;
sex2=sex ;
endcomp ;
compute after sex ;
sex2='Average for ' || sex ;
endcomp ;
compute after ;
sex2='Overall Average' ;
endcomp ;

title2 'PROC REPORT and more' ;
run ;


語法中第二行column後多加一個新變項叫做sex2其用意是增加sex的相同變項並給予改名以及後續的應用

在第三行noprint則是將原有的Sex變項作隱藏(可以不打此語法)

在第四行時則定義sex2的變項名稱為"Sex"(有點是說原Sex變項以用來做排序而後面的Sex2則是篡位原來Sex的標題"label")

第九行至第十一行是命名Sex2作為原Sex的標題項目(因為原Sex已被用來做排序了,所以新增Sex2來覆蓋原來的功用)

第十二行至第十四行則為每個sex分類break斷行後的平均值做個標題,其中sex2='Average for ' || sex ;只是說將sex2更名為Average for || sex(F or M ),而||是SAS連結文字用的符號

同理第十五至第十七則是sex2='Overall Average' ;最後為總平均的標題更名為Overall Average

其結果如下圖


接下來則是在把上述的結果報表再次的作修飾的動作


proc format ;
value $gender 'F'='females'
'M'='males' ;
run ;

proc report data=sashelp.class nowd headline ;
column sex name age ;
define sex / order width=3 ;
define age / mean ;
break after sex / skip ;
compute after sex ;
text='Average for ' || strip(put(sex, $gender.)) || ' is ' || put(age.mean, 4.1) ;
line ' ';
line text $40. ;
endcomp ;

compute after ;
line 'Overall Average is ' age.mean 4.1 ;
endcomp ;

title2 'PROC REPORT and more, again' ;
run ;



在第一行至第四行為proc format語法,其用意是宣告gender這個新變項被引用時其值F改為females,M改為males

在第五行時proc report後加上一個宣告headline顧名思義就是加個標頭線

在第八行時定義age做平均(mean)的計算並且呼應後面幾行用到的語法age.mean
若定義為總和sum時後面幾行的語法改為age.sum

第十行至第十三行不同於上一個範例語法的使用,此次則是新增一個類似文字敘述的語法
在第十一行先宣告text文字敘述的特性,其中strip()則為將文字變項前後之間做縮排的動作,也就是將
'Average for '與sex變項與' is '三者之間做縮排(若把strip()取消就可以看出差異點了),而put語法則是導入age.mean資料並且宣告其字元長度(4.1為4個字元長且小數點取1位)
接著第十二行則是新增行並以空白''做為表現,也可改為line '--------------------------';(有點類似自行做圖)
在第十三行則是將剛剛的text文字做使用的動作並且給予字元特徵40個字元長度

第十五行至第十七行與上一個範例類似,在最後做總平均的計算

其結果如下





4.與PROC TABULATE做比較

proc tabulate在SAS中是用來歸納特定變項的基本統計資料,例如平均數、樣本數等

其語法如下


title 'Summary Statistics' ;
proc tabulate data=sashelp.class ;
class sex ;
var age ;
table sex, age*(n*f=4. mean*f=6.2) ;
title2 'PROC TABULATE' ;
run ;


其中 class 指定分層變項,var 為分析變性
proc tabulate程序主要語法為table的宣告
其中先以sex作報表分類再以逗號區隔計算age的樣本數(n)、平均數(mean);而括號內f為宣告格式

結果如下圖


而在proc report語法中可以做出類似的報表
語法如下

proc report data=sashelp.class nowd split='~' box ;
column sex age age=avg_age ;
define sex / group width=3 ;
define age / n 'N' format=4.0 width=4;
define avg_age / mean 'Average~Age' format=6.2 width=7;
title2 'PROC REPORT' ;
run ;


眼尖的話因該就會發現其實只是要proc report程序做點外觀的變化,也就是增加box的宣告
結果如下圖

或者是可以把box改為headline的宣告其結果就如下圖



列聯表的應用
想到列聯表因該就會想到proc freq的使用
proc tabulate則是可以做出類似的輸出
語法如下

options missing='0' ;
title 'Cross-tabulation' ;
proc tabulate data=sashelp.class ;
class sex age ;
table age, sex*n*f=4. ;
title2 'PROC TABULATE' ;
run ;

上述語法只是要求顯示樣本數而已
其結果如下



利用proc report語法也能求出類似報表
語法如下
proc report data=sashelp.class nowd headline ;
column age sex ;
define age / group ;
define sex / across width=3 right ;
title2 'PROC REPORT' ;
run ;

語法across是用來宣告sex變項做交叉表的分類,而因沒有再分析其他變項,則sex變項僅計算其次數(n)

其結果如下圖



若想做較複雜的列聯關係表,如性別與年齡分層後的身高平均
如下為proc tabulate提供的做法

options missing='?';
title 'Cross-tabulation with Summary' ;
proc tabulate data=sashelp.class ;
class sex age ;
var height ;
table age, sex*height*mean*f=6.1 ;
title2 'PROC TABULATE' ;
run ;

如下圖僅是根據age, sex分層將height計算其平均




而proc report的做法也有所相似如下

proc report data=sashelp.class nowd split='~' headline ;
column age sex, height ;
define age / group ;
define sex / across '__Sex__' width=3 right ;
define height / analysis mean 'Average~Height'
format=6.1 width=8 ;

title2 'PROC REPORT' ;
run ;



增加, height 用來宣告sex分類下的顯示
define height / analysis mean 'Average~Height'
format=6.1 width=8 ;
的宣告計算其結果

其結果如下



若想計算列聯表中樣本數的百分比資料,有如proc freq所計算的百分比
在proc tabulate語法如下

title 'Percentages' ;
proc tabulate data=sashelp.class ;
class sex ;
table sex, n="樣本數" pctn="百分比";
title2 'PROC TABULATE' ;
run ;


僅是在table做一個計算的宣告 pctn 計算Sex變項的百分比

結果如下圖



而利用proc report的方式語法如下

proc report data=sashelp.class nowd box ;
column sex N pctn ;
define sex / group width=3;
define n / width=5 ;
define pctn / '%' format=percent7.1 ;
title2 'PROC REPORT' ;
run ;


結果如下圖





5.與PROC MEANS做比較


最後若想要做出有如proc means程序一樣能夠提供多種基本描述性統計資料
其語法如下

title 'Summary Statistics 2' ;
proc means data=sashelp.class mean std min max maxdec=1;
class sex ;
var height ;
title2 'PROC MEANS' ;
run ;

proc means有本身預設的描述性統計結果的顯示,而上述則欲顯示平均、標準差、最小值及最大值
其結果如下




如利用proc report的語法欲做出如proc means類似報表,其語法如下

proc report data=sashelp.class nowd split='~' headline ;
column sex height, (n mean std min max) ;
define sex / group width=3 ;
define height / '__Height__' ;
define n / 'N' width=3 ;
define mean / 'Mean' format=5.1 ;
define std / 'Std~Dev' format=5.2 ;
define min / 'Min' format=5.1 ;
define max / 'Max' format=5.1 ;

title2 'PROC REPORT' ;
run ;

上述語法是將各描述性統計值須先做宣告的動作
其結果如下

2008年4月7日 星期一

Any WAY you Want it: Getting the Right TYPEs of Observations Out of PROC SUMMARY or MEANS

原文出處:http://www2.sas.com/proceedings/forum2008/087-2008.pdf




常使用敘述統計語法如proc means等,會有將資料output的經驗,不過轉出的資料常會有意無意看到資料裡會多了一些非期望的變項如_TYPE_ _FREQ_ _STAT_等,而這些變項有是其他用途的.
其中WAYS,TYPES使用如下


1.常用output方式

data king;
input x1 x2 y;
cards ;
1 1 10
1 1 12
1 2 21
1 2 13
1 3 21
1 3 30
2 1 15
2 1 18
2 2 19
2 2 20
2 3 25
2 3 9
3 1 30
3 1 22
3 2 14
3 2 13
3 3 27
3 3 18
;
proc means ;
class x1 x2 ;
var y;
output out=k1 ;
proc print data=k1;
run;



此時會轉出k1這個資料檔,並增加了幾個變項
如x1,x2,_TYPE_,_FREQ_,_STAT_,y
其中x1,x2為原資料分層後的結果
_TYPE_為x1,x2的分層後的聯合分類變項,若分層很多時_TYPE_會有更多組方便使用者再次處理資料
_FREQ_為_TYPE_分組後的次數
_STAT_為轉出時未指定類型則定義為預設值資料,其中有N,MIN,MAX,MEAN,STD等


2.使用WAYS增添實用性(分類變項的因子數)
在語法中鍵入output後面/ WAYS

proc means ;
class x1 x2 ;
var y;
output out=k1 mean=mean / WAYS;
proc print data=k1;
run;



此語法會使轉出之資料增加 _WAYS_變項
是用來表達其分類變項x1,x2的因子數(way)
若資料(x1,x2)呈現(.,.)則_WAY_=0
若資料(x1,x2)呈現(1,.)或(.,1)則_WAY_=1
為一因子(one-way)
若有資料分類為(x1,x2,x3,x4,x5)呈現(1,1,1,1,1)則_WAY_=5




3.NWAY功能(保留最大因子數之觀察值)
使用此功能僅會顯示出因子數最大之觀察值(full)

proc means NWAY;;
class x1 x2 ;
var y;
output out=k1 mean=mean /ways;
proc print data=k1;
run;







4.WAYS(因子數選擇)
選擇要出現的因子數為多少

proc means ;
class x1 x2 ;
var y;
WAYS 1;
output out=k1 mean=mean / WAYS;
proc print data=k1;
run;



選擇因子數可以是複合型態,如下只顯示因子數0與2之觀察值

proc means ;
class x1 x2 ;
var y;
WAYS 0 2;
output out=k1 mean=mean / WAYS;
proc print data=k1;
run;






5.TYPE的使用
此語法是要用來配合聯合分類變數(如x1,x2)時顯示觀察值所用

proc means ;
class x1 x2 ;
var y;
TYPE x1 x2 x1*x2 ();
output out=k1 mean=mean / WAYS;
proc print data=k1;
run;


其中x1是顯示聯合分類變數有資料的(1,.)
x2是顯示聯合分類變數有資料的(.,1)
x1*x2是顯示聯合分類變數有資料(1,1)
()是顯示皆無資料(.,.)

proc means

Any WAY you Want it: Getting the Right TYPEs of Observations Out of PROC SUMMARY or MEANS

2008年2月1日 星期五

Receiver Operating Characteristic (ROC) Curves

原文出處:http://www2.sas.com/proceedings/sugi31/210-31.pdf




除了須具備Receiver Operating Characteristic (ROC) Curves基本概念外,尚需了解SAS計算所用的程序語法procedures,本文預計會有SAS/STAT中的FREQ, LOGISTIC, MIXED and NLMIXED以求出ROC curve 與平滑曲線圖


以下分為5個步驟
1. BASIC CONCEPTS: BINARY PREDICTOR
2. THE ROC CURVE
3. AREA UNDER THE ROC CURVE
4. THE BINORMAL ROC CURVE
5. COMPARING TWO ROC CURVES


1. BASIC CONCEPTS: BINARY PREDICTOR
基本概念可參考文獻Metz(1978)(該文獻內容解釋非常完整)

此外文中提到欲比較兩組在某閾值下的比例,以下面為例,x為0,1兩組,以y分類0,1,所求之列聯表

data king ;
input y x w;
cards;
0 0 29
0 1 6
1 0 4
1 1 38
;

proc freq;
table y*x;
weight w;
run;





而為了要檢視x兩組之比例狀況故使用下列語法

data king ;
input y x w;
cards;
0 0 29
0 1 6
1 0 4
1 1 38
;
proc sort;by x ;
proc freq;
by x;
table y / BINOMIAL;
weight w;
run;


其樣本比例檢定之結果如下圖

其中ASE為樣本比例之標準誤





2. THE ROC CURVE
為了進一步說明ROC曲線,故創建以下資料並搭配原文以進一步說明

data roc;
input Gold suv;
cards;
1 3
1 4
1 5
1 4
1 5
1 6
1 7
1 8
1 9
1 4
1 2
1 3
1 5
1 6
1 7
1 6
1 5
1 4
1 5
1 5
0 1
0 2
0 3
0 4
0 5
0 6
0 2
0 3
0 2
0 1
0 1
0 2
0 2
0 3
0 2
0 3
0 1
0 2
0 3
0 2
0 2
0 2
;
proc logistic noprint;
model gold=suv / outroc=ROCData;
run;
symbol1 v=dot i=join;
proc gplot data=ROCData;
plot _sensit_*_1mspec_;
run;quit;


因Gold有兩組(0,1)之測量結果suv,繪製ROC曲線



然而若要繪至更漂亮之ROC曲線圖可參考吾所寫之其他文章,應用SAS繪製ROC curve圖




3. AREA UNDER THE ROC CURVE
而通常為了表達ROC曲線的表現是否比較好,會以曲線下面積(AREA UNDER THE ROC CURVE, AUC)做表示,
而如何求出此面積值可以邏輯式回歸分析表中之 Association of Predicted Probabilities and Observed Responses報表內C值作為結果


或是參考,應用SAS繪製ROC curve圖文中巨集語法%roc(DATA= , VAR= , RESPONSE= , CONTRAST= , ALPHA= , DETAILS=)之使用



4. THE BINORMAL ROC CURVE



5. COMPARING TWO ROC CURVES




參考文獻
1. Metz, C.E. (1978), "Basic principles of ROC analysis," Seminars in Nuclear Medicine, 8(4), 283-298.

2008年1月26日 星期六

讓你的ODS PRINTER Statement進入21世紀

原文出處:http://www2.sas.com/proceedings/sugi31/227-31.pdf




繼ODS再次進化後,ODS PRINTER從8.2版本到目前的9.2版本,其報表輸出多了很多編修方式,Scott Huntley, Cary,則提出了一些輸出為PDF檔的方法

起初的ODS語法可以先參考ODS的應用ODS的應用2


options nonumber nodate;
ods escapechar = "^";
ods pdf file="example1.pdf";
title1 "^S={just=L }This title is blue and left justified";
title2 "^S={just=R }This title is red and right justified";
title3 "^S={just=C }This title is green and centered";
proc print data=sashelp.class(obs=1);run;
ods _all_ close;



escapechar = "^"是用來使^S={ }在TITLE中有作用的語法使得下方說明能夠有作用
而依照作者所說明,^S={ }可以埋入文字標題字串內,且是用來定義文字標題字串內各種形式的文字輸出,有點類思WORD中的文字編輯,而支援的語法有以下
ABSTRACT, ACTIVELINKCOLOR, ASIS, BACKGROUND, BACKGROUNDIMAGE, BODYSCROLLBAR, BODYSIZE, BORDERCOLOR, BORDERCOLORDARK, BORDERCOLORLIGHT, BORDERWIDTH, BOTTOMMARGIN, BULLET, CELLPADDING, CELLSPACING, CONTENTPOSITION, CONTENTSCROLLBAR, CONTENTSIZE, CONTRASTCOLOR, CSSSTYLE, CSSTEXT, DESCRIPTION, DROPSHADOW, ENDCOLOR, FILLRULEWIDTH, FLYOVER, FONT, FONT_FACE, FONT_SIZE, FONT_STYLE, FONT_WEIGHT, FONT_WIDTH, FOREGROUND, FRAME, FRAMEBORDER, FRAMEBORDERWIDTH, FRAMESPACING, GRADIENT_DIRECTION, HREFTARGET, HTMLCLASS, HTMLCONTENTTYPE, HTMLDOCTYPE, HTMLID, HTMLSTYLE, IMAGE, IMAGESTYLE, INDENT, JUST, LEFTMARGIN, LINESTYLE, LINETHICKNESS, LINKCOLOR, LISTENTRYANCHOR, LISTENTRYDBLSPACE, MARKERSIZE, MARKERSYMBOL, MINOR, NEUTRALCOLOR, NOBREAKSPACE, OFFSET, OUTPUTHEIGHT, OUTPUTWIDTH, OVERHANGFACTOR, PAGEBREAKHTML, POSTHTML, POSTIMAGE, POSTTEXT, PREHTML, PREIMAGE, PRETEXT, PROTECTSPECIALCHARS, RIGHTMARGIN, RULES, STARTCOLOR, TAGATTR, THRESHOLD, TICKDISPLAY, TOPMARGIN, TRANSPARENCY, URL, VISITEDLINKCOLOR, VJUST, WATERMARK


可能因SAS版本不同所以吾的^S={ }有稍微差異(9.2版本),不過對於標題的修改可以參照title的說明就可以修改了如下

title3 color=red "^S={just=C }This title is green and centered";



稍微整理後如下

options nonumber nodate;
ods escapechar = "^"
ods pdf file="example1.pdf";
title1 color=red "^S={just=l}This title" color=blue " is blue and left justified";
proc print data=sashelp.class;
run;
ods _all_ close;







當然為了讓輸出更為多樣化,吾也適度修改了內容以達到報表的美觀

options nonumber nodate;
ods escapechar = "^";
ods pdf file="example1.pdf" style=sasweb;
title color=red "^S={just=l font_size=10}This is kingbee " color=blue " testing ";
footnote color=blue "This is tesitng for PDF output" ;
proc print data=sashelp.class;
run;
ods pdf text="測試用的資料";
ods _all_ close;



而其中用到了style=sasweb,為ODS的輸出時報表的美觀
另外ods pdf text="";,是可以將想要寫入報表的文字敘述用的方法

2008年1月18日 星期五

proc timeplot

繪製時間圖

繪製時間圖

原文出處:http://www2.sas.com/proceedings/forum2007/029-2007.pdf




雖然SAS提供有利的函數LAG,有利於對有重複相關的觀察值來做時間上的差值計算,例如第一筆與第二筆觀察值是同一個人只是時間上的前後,所以可以利用LAG函數來做時間差計算
所以原作者Pon Su提供一種方便的計算方式,並利用SAS的程序PROC TIMEPLOT來美化時間資料
以下為作者提供之範例可供使用者直接套用練習

options center nodate nonumber ls=64;
data temp;
input id startdt:mmddyy8. stopdt:mmddyy8. ;
datalines;
101 01/01/05 01/09/05
101 01/05/05 01/20/05
101 01/16/05 01/18/05
101 01/26/05 01/31/05
102 01/01/05 01/07/05
102 01/05/05 01/07/05
102 01/06/05 01/17/05
102 01/14/05 01/27/05
102 01/29/05 01/31/05
;
run;

*範例中可以看到編號(ID)中有前後兩個時間點資料,並以下方語法做處理,而重點在於使用了LAG函數來加以處理時間資料;
data temp1;
set temp;
format startdt stopdt lagstop mmddyy8. ;
real_days = stopdt - startdt + 1;
lagstop =lag(stopdt);
if id = lag(id) then
if lagstop >= stopdt then
real_days = 0;
else if lagstop >= startdt then
real_days = stopdt - lagstop;
run;

****************************************************************************;
* The following comments are copied from SAS Procedure Guide manuals. ;
* The TIMEPLOT procedure plots one or more variables over time intervals. ;
* OVERLAY plots all requests in one plot statement on one set of axes. ;
* HILOC connects the leftmost plotting symbol to the rightmost with hyphens.;
****************************************************************************;
title "SGF 2007 Coders' Corner Demo";
*並將上述時間處理呈現出來,利用了以下語法PROC TIMEPLOT;
proc timeplot data=temp1;
plot startdt ='<' stopdt='>' / overlay ref='15JAN05'd hiloc;
by id;
run;

*作者再簡單的將時間資料做呈現;
proc print data=temp1;
run;

proc sql;
select id, sum(real_days) as duration_in_days
from temp1
group by id
order by id;
quit;


最後如下圖





以下為我適度修改後的說明
1.時間資料的建立

data king1;
input ID Pretime: mmddyy10. Posttime: mmddyy10. ;
cards;
1 01/01/2006 05/01/2006
1 05/02/2006 01/01/2007
1 12/01/2006 01/15/2008
2 12/05/2005 01/06/2007
2 09/16/2007 12/02/2007
2 11/29/2007 01/15/2008
3 01/01/2005 01/02/2008
3 04/04/2006 01/15/2008
3 02/01/2007 01/02/2008
;
proc print;
run;


需要先宣告時間變項的時間格式如mmddyy8.或是mmddyy10.,而主要目的是先將資料轉為SAS的內置日期(1960年1月1日為起始)距離今天的"日數",例如時間為01/22/1977以mmddyy10.為格式,則SAS內建日期為6231日,而其他日期格式請參考SAS說明
以上是建立時間之資料方式,若使用者有自行的時間資料時,只要能夠轉換為SAS內建日期就可以直接接續下一步了

2.時間資料繪製

proc timeplot data=king1;
plot Pretime ='<' posttime='>' / overlay ref='15JAN05'd hiloc;
by id;
run;


其中overlay是用在圖的重疊(若是使用proc gplot有多張點圖重疊),在此是將時間圖畫的Pretime與posttime重疊起來,如<_____>
ref='15JAN05'd為時間基準線,只要修改引號內的時間(date.)
hiloc為重疊後將時間用連接線連起來,如<--------->

2008年1月9日 星期三

MACRO

利用MACRO語法將SAS資料直接繪至成EXCEL圖檔

Receiver Operating Characteristic (ROC) Curves

利用MACRO語法將SAS資料直接繪製成EXCEL圖檔

原文出處:http://www2.sas.com/proceedings/forum2007/002-2007.pdf


此原文作者Ted Conway, Chicago, IL介紹利用SAS中的MACRO語法配合Visual Basic語法來實現大量資料檔其描述性統計特性:長條圖(Bar)與線(Line)圖

此法概念來自於原出處如下圖

步驟如下

1.先建立SAS MACRO語法定義EXCEL圖檔
2.利用SAS執行時將建立的MACRO語法轉換為EXCEL的VBA語言
3.再將VBA語言表現在EXCEL資料表上並繪製出圖檔




1.先將以下MARCO匯入SAS並執行

作者提供的MACRO語法


%macro chart(type, name=, charttype=bar, across=1, cell=a1, data=, catvar=, xvar=, yvar=, yformat=, ymin=0, ymax=, yint=);
%if &type=workbook %then %do;
%global gblworkbook; %let gblworkbook=&name;
data _null_;
file "c:\temp\chart.vbs" mod; * Note: .vbs file should not exist at start of processing;
put 'Set XL = CreateObject("Excel.Application")' / 'XL.Visible=True' /
'XL.Workbooks.add' / "XL.ActiveWorkbook.SaveAs ""&gblworkbook"", -4143";
%end;
%if &type=worksheet %then %do;
data _null_; file "c:\temp\chart.vbs" mod; put "XL.Sheets.Add.name = ""&name"""; %global gblworksheet; %let gblworksheet=&name;
%end;
%if &type=chart %then %do;
proc sql noprint;
select distinct &catvar into :categories separated by '|' from &data order by &catvar;
%let catnum=1;
%let cat=%scan(&categories,&catnum,'|');
%do %while("&cat"^="");
%let lrow=%eval(%sysfunc(floor(%eval(&catnum-1)/&across))+1);
%let lcol=%sysfunc(mod(&catnum,&across));
%if &lcol=0 %then %let lcol=&across;
data _null_;
set _last_(where=(&catvar="&cat")) end=eof;
length xvalues yvalues $ 32000;
retain xvalues yvalues '';
xvalues=trim(xvalues)||'""'||trim(&xvar)||'"",';
yvalues=trim(yvalues)||trim(&yvar)||',';
if eof;
file "c:\temp\chart.vbs" mod;
put "XL.windows(""%scan(&gblworkbook,-1,'\')"").Activate" / 'XL.Range("A1").Select' / "XL.Charts.Add";
%if &charttype=bar %then put "XL.activechart.ChartType = 51";; %if &charttype=line %then put "XL.activechart.ChartType = 4";;
put "XL.activechart.SeriesCollection.NewSeries" / "XL.activechart.SeriesCollection(1).XValues = ""={" xvalues +(-2) '}"' /;
put 'XL.activechart.SeriesCollection(1).Values = "={' yvalues +(-2) '}"' / 'XL.activechart.SeriesCollection(1).Name = "=""' "&cat" '"""' /
'XL.activechart.Location 2, "' "&gblworksheet" '"'; *2=xlLocationAsObject;
put 'XL.activechart.Axes(1).MajorTickMark = -4142' / 'XL.activechart.Axes(1).MinorTickMark = -4142' / 'XL.activechart.Axes(2).MajorTickMark = -4142' /
'XL.activechart.Axes(2).MinorTickMark = -4142' / "XL.activechart.Axes(2).MinimumScale = &ymin" / "XL.activechart.Axes(2).MaximumScale = &ymax" /
"XL.activechart.Axes(2).MinorUnit = &yint" / "XL.activechart.Axes(2).MajorUnit = &yint" / 'XL.activechart.Axes(2).TickLabels.NumberFormat =' ""&yformat"";
put 'x = XL.worksheets(' """&gblworksheet""" ').ChartObjects(XL.worksheets(' """&gblworksheet""" ').ChartObjects.Count).Left';
%if &lcol=1 %then
put 'XL.worksheets(' """&gblworksheet""" ').ChartObjects(XL.worksheets(' """&gblworksheet""" ').ChartObjects.Count).Left = XL.worksheets(' """&gblworksheet"""
').Columns(' "XL.range(""&cell"").column" ').Left'%str(;);
%else %do;
put 'XL.worksheets(' """&gblworksheet""" ').ChartObjects(XL.worksheets(' """&gblworksheet""" ').ChartObjects.Count).left = _';
put 'XL.worksheets(' """&gblworksheet""" ').Columns(' "XL.range(""&cell"").column" ').Left + _';
put "(&lcol-1) * " 'XL.worksheets(' """&gblworksheet""" ').ChartObjects(XL.worksheets(' """&gblworksheet""" ').ChartObjects.Count).width';
%end;
put 'XL.activechart.Legend.Delete';
%if &lrow=1 %then
put 'XL.worksheets(' """&gblworksheet""" ').ChartObjects(XL.worksheets(' """&gblworksheet""" ').ChartObjects.Count).Top = XL.worksheets(' """&gblworksheet"""
').Rows(' "XL.range(""&cell"").row" ').Top'%str(;);
%else %do;
put 'XL.worksheets(' """&gblworksheet""" ').ChartObjects(XL.worksheets(' """&gblworksheet""" ').ChartObjects.Count).Top = _';
put 'XL.worksheets(' """&gblworksheet""" ').Rows(' "XL.range(""&cell"").row" ').Top + _';
put "(&lrow-1) * " 'XL.worksheets(' """&gblworksheet""" ').ChartObjects(XL.worksheets(' """&gblworksheet""" ').ChartObjects.Count).height';
%end;
%let catnum=%eval(&catnum+1);
%let cat=%scan(&categories,&catnum,'|');
%end;
%end;
%if &type=create %then %do;
data _null_; file "c:\temp\chart.vbs" mod; put "XL.ActiveWorkbook.Save"; run; x 'c:\temp\chart.vbs';
%end;
%mend;




2.將SAS MACRO語法執行並將起始語法設定好
依照原作者,在MACRO語法中共分為四個步驟皆是以%chart();開頭

1.%chart(workbook, name=c:\temp\chart.xls);
2.%chart(worksheet, name=TestBar);
3.%chart(chart, charttype=bar,cell=a1, across=1, data=work.king , catvar=catvar , xvar=xvar , yvar=yvar, yFormat="#,##0" , ymax=10000, yint=2000 );
4.%chart(create);




Step 1.%chart(workbook, name=c:\temp\chart.xls);
需先存在workbook關鍵字,並在name=後面打上excel未來的存放位置,預設值為c:\temp\chart.xls,若遇到繪出位置無該資料夾則須先自行建立該資料夾,如c:內無temp資料夾,則自行先建立temp資料夾方可使用

Step 2.%chart(worksheet, name=TestBar);
須先打上worksheet,為excel檔案內的分頁,並將命名為name=TestBar,也可自行命名其他分頁名稱

Step 3.%chart(chart, charttype=bar,cell=a1, across=1, data=work.king , catvar=catvar , xvar=xvar , yvar=yvar, yFormat="#,##0" , ymax=10000, yint=2000);
須先打上chart
charttype=bar,為輸出在EXCEL檔時圖檔為bar,也可打line
cell=a1,為圖檔的起始位置,此為EXCEL檔內a1 cell的位置
across=1,為圖檔並排的數目,若圖檔預計有10張,若across=2則左右會有兩張並排而垂直會有5張
data=,為SAS程式內欲輸出的檔案
catvar=,為SAS檔案欲輸出的分層變項(須為文字型態),內有十層即可繪製出10張圖檔
xvar=,為SAS檔案中欲繪製在EXCEL圖檔中x軸的變項(須為文字型態)
yvar=,為SAS檔案中欲繪製在EXCEL圖檔中y軸的變項(須為數字型態)
yFormat="#,##0",EXCEL圖檔中y軸座標格式,可加也可不加
ymax=10000,顧名思義為y軸資料的最大值
yint=2000,為y軸資料個間距

Step 4.%chart(create);
打上create做為結尾的部份,打上此段語法後SAS執行完就會將資料繪製到EXCLE檔圖檔中

附註:Step 3. 可重複出現例如同時繪製chart與line圖 可以在語法中打2組Step 3.的語法


實測如下

data king;

input catvar$ xvar$ yvar;

cards;
1 5000 200
1 4000 300
1 2000 400
1 3000 200
1 1000 200
1 3000 200
2 1000 300
2 2000 500
2 3000 100
2 2000 200
2 5000 200
3 1000 100
3 3000 200
3 5000 600
3 2000 1000
3 10000 1500
;
run;


%chart(workbook, name=c:\temp\chart.xls);
%chart(worksheet, name=king);
%chart(chart, charttype=bar,cell=a1, across=1, data=work.king , catvar=catvar , xvar=xvar , yvar=yvar, yFormat="#,##0" , ymax=10000, yint=2000 );
%chart(create);




完成後如下圖(下圖為EXCEL 2007 表示也能用)




作者提供以下範例可直接複製並執行


proc sql; * Create some sample data;
create table prod1993 as
select product, month as monum, put(month,monname3.) as month, sum(actual) as actual
from sashelp.prdsale(where=(year=1993)) group by 1, 2, 3 order by 1, 2;
%chart(workbook, name=c:\temp\chart.xls);
%chart(worksheet, name=TestBar); * Example #1 – Three-Across Bar Charts;
%chart(chart, charttype=bar, cell=b2, across=3, data=prod1993, catvar=product, xvar=month,
yvar=actual, yFormat="#,##0", ymax=10000, yint=2000);
%chart(worksheet, name=TestLine); * Example #2 – One-Across Line Charts;
%chart(chart, charttype=line, cell=a1, across=1, data=prod1993, catvar=product, xvar=month,
yvar=actual, yFormat="#,##0", ymax=10000, yint=2000);
%chart(worksheet, name=TestBoth); * Example #3 – Three-Across Bar and Line Charts;
%chart(chart, charttype=bar, cell=a1, across=3, data=prod1993, catvar=product, xvar=month,
yvar=actual, yFormat="#,##0", ymax=10000, yint=2000);
%chart(chart, charttype=line, cell=a40, across=3, data=prod1993, catvar=product, xvar=month,
yvar=actual, yFormat="#,##0", ymax=10000, yint=2000);
%chart(create);





3.再將VBA語言表現在EXCEL資料表上並繪製出圖檔


以下為MACRO執行後在EXCEL內實現的VBA程式碼,僅供參考


Set XL = CreateObject("Excel.Application")
XL.Visible=True
XL.Workbooks.add
XL.ActiveWorkbook.SaveAs "c:\temp\chart.xls", -4143
XL.Sheets.Add.name = "TestBar"
XL.ActiveSheet.PageSetup.CenterHorizontally = True
XL.ActiveSheet.PageSetup.CenterVertically = True
XL.ActiveSheet.PageSetup.Orientation = 2
XL.ActiveSheet.PageSetup.FitToPagesWide = 1
XL.ActiveSheet.PageSetup.FitToPagesTall = 1
XL.ActiveSheet.PageSetup.Zoom = False
XL.windows("chart.xls").Activate
XL.Range("A1").Select
XL.Charts.Add
XL.activechart.ChartType = 51
XL.activechart.SeriesCollection.NewSeries
XL.activechart.SeriesCollection(1).XValues = "={""Jan"",""Feb"",""Mar"",""Apr"",""May"",""Jun"",""Jul"",""Aug"",""Sep"",""Oct"",""Nov"",""Dec""}"
XL.activechart.SeriesCollection(1).Values = "={4085, 5025, 4918, 6999, 5727, 7615, 8189, 5754, 4038, 5284, 4890, 6939}"
XL.activechart.SeriesCollection(1).Name = "=""BED"""
XL.activechart.Location 2, "TestBar"
XL.activechart.Axes(1).MajorTickMark = -4142
XL.activechart.Axes(1).MinorTickMark = -4142
XL.activechart.Axes(2).MajorTickMark = -4142
XL.activechart.Axes(2).MinorTickMark = -4142
XL.activechart.Axes(2).MinimumScale = 0
XL.activechart.Axes(2).MaximumScale = 10000
XL.activechart.Axes(2).MinorUnit = 2000
XL.activechart.Axes(2).MajorUnit = 2000
XL.activechart.Axes(2).TickLabels.NumberFormat ="#,##0"
x = XL.worksheets("TestBar").ChartObjects(XL.worksheets("TestBar").ChartObjects.Count).Left
XL.worksheets("TestBar").ChartObjects(XL.worksheets("TestBar").ChartObjects.Count).Left =
XL.worksheets("TestBar").Columns(XL.range("b2").column).Left
XL.activechart.Legend.Delete
XL.worksheets("TestBar").ChartObjects(XL.worksheets("TestBar").ChartObjects.Count).Top =
XL.worksheets("TestBar").Rows(XL.range("b2").row).Top