公告

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

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


2008年4月30日 星期三

Using Macro and ODS to Overcome Limitations of SAS® Procedures

原文載點:http://www.nesug.info/Proceedings/nesug07/cc/cc26.pdf

在 SAS 中,只有 PROC REG、PROC LOGISTIC 和 PROC PHREG 具有 model selection 的功能,其餘諸如 PROC GENMOD、PROC CATMOD 或 PROC MIXED 都需要用「手動」的方式來挑選最佳模式。本文利用 ODS 的功能,提供一個 macro 程式讓 PROC GENMOD 可以進行自動的 model selection 動作,可大幅節省時間並且減少手動挑選模式的過程中所可能產生的錯誤。

首先必須先執行一個名叫 MdStmt 的 macro 將 PROC GENMOD 所產生的 Type 3 test 報表另存成一個新檔。程式如下:
  %macro MdStmt(
resvar = /*response variable */
,expvar = /*list of explanatory variables, separated by ' ' */
,clsvar = /*classification variables in the CLASS statement separated by ' ' */
);

ods output Type3=pval(rename=source=parm);
proc genmod data=indat descending;
class S &clsvar;
model &resvar= &expvar /dist=bin link=logit type3 lrci;
repeated subject=S /type=cs corrw covb;
title "&resvar = &expvar";
run;
ods output close;
%mend MdStmt;


此 macro 包含三個參數:
  • resvar:要放在 model statement 等號左邊的反應變數
  • expvar:要放在 model statement 等號右邊的解釋變數
  • clsvar:要放在 class statement 的類別變數
不過使用者無須直接使用這個 macro,因為另一個真正的主程式 %MdSelect 會自動去執行 %MdStmt。主程式如下所示:
  %macro MdSelect(
var= /*response variable */
,intvar= /*initial explanatory variables for full model */
,catvar= /*categorical explanatory variables */
,slstay= /*criterion for removing variable */
);

%let var=%upcase(&var);
%let intvar=%upcase(&intvar);
%let catvar=%upcase(&catvar);

%*-------------------------------------------------------------------------*;
%* Create empty dataset "step" with only one column "parm". It will be *;
%* merged with "pval" from PROC GENMOD by "parm" *;
%*-------------------------------------------------------------------------*;
proc sql;
create table step_&var (parm char(9));
quit;

%let i=1;
%do %until (&pmax<=&slstay); %if &i = 1 %then %MdStmt(resvar=&var ,expvar=&intvar, clsvar=&catvar); %*initial model; %else %do; %MdStmt(resvar=&var ,expvar=&varlist, clsvar=&catvar); %*reduced model; %end; proc sort data=step_&var; by parm; proc sort data=pval; by parm; data step_&var; merge step_&var pval; by parm; p&i=put(ProbChiSq, pvalue6.3); drop ProbChiSq ChiSq DF; run; proc sql noprint; select max(ProbChiSq) into :pmax from pval; select distinct parm into :varlist separated by ' ' from pval having ProbChiSq^=max(ProbChiSq); quit; %let i=%eval(&i+1); %end; proc print data=step_&var; title "&var: model selection process"; run; %mend MdSelect;


這程式包含四個參數:
  • var:要放在 model statement 等號左邊的反應變數
  • intvar:要放在 model statement 等號右邊的解釋變數
  • catvar:要放在 class statement 內的類別變數
  • slstay:刪除變數的準則。這個值是要拿去跟 p-value 比的。通常是設定 0.1 或 0.5。
以下範例是假設反應變數是 Y1,解釋變數是 C1, C2, C3, M1, M2, M3, M4, M5, M6, M7,其中 C1, C2, C3 是類別變數,刪除變數的準則是 0.5。程式如下:

%MdSelect(var=Y1, intvar=C1 C2 C3 M1 M2 M3 M4 M5 M6 M7, catvar=C1 C2 C3, slstay=0.5);


不過這個 macro 有個缺陷(我自己發現的)。在 %MdStmt 中,ID 變數被固定為 S,而 covariance structure 的形式被固定成 cs。同理,model statement 後面的 option 也被固定為 dist=bin 和 link=logit,表示這個模式只能拿來做最簡單的 logistic regression model with binary response。因此,可以把 %MdStmt 改成:
  %macro MdStmt(
idvar= /*ID variable*/
,resvar = /*response variable */
,expvar = /*list of explanatory variables, separated by ' ' */
,clsvar = /*classification variables in the CLASS statement separated by ' ' */
,resdist= /*distribution of response variable*/
,linkfunc= /*link function*/
,covstr= /*covariance structure type*/
);

ods output Type3=pval(rename=source=parm);
proc genmod data=indat descending;
class &idvar &clsvar;
model &resvar= &expvar /dist=&resdist link=&linkfunc type3 lrci;
repeated subject=&idvar /type=&covstr corrw covb;
title "&resvar = &expvar";
run;
ods output close;
%mend MdStmt;


然後 %MdSelect 改成:
  %macro MdSelect(
id= /*id variable*/
,var= /*response variable */
,intvar= /*initial explanatory variables for full model */
,catvar= /*categorical explanatory variables */
,slstay= /*criterion for removing variable */
,dist= /*distribution of response variable*/
,link= /*link function*/
,type= /*covariance structure type*/
);

%let var=%upcase(&var);
%let intvar=%upcase(&intvar);
%let catvar=%upcase(&catvar);

%*-------------------------------------------------------------------------*;
%* Create empty dataset "step" with only one column "parm". It will be *;
%* merged with "pval" from PROC GENMOD by "parm" *;
%*-------------------------------------------------------------------------*;
proc sql;
create table step_&var (parm char(9));
quit;

%let i=1;
%do %until (&pmax<=&slstay); %if &i = 1 %then %MdStmt(idvar=&id, resvar=&var ,expvar=&intvar, clsvar=&catvar, resdist=&dist, linkfunc=&link, covstr=&cov); %*initial model; %else %do; %MdStmt(idvar=&id, resvar=&var ,expvar=&varlist, clsvar=&catvar, resdist=&dist, linkfunc=&link, covstr=&cov); %*reduced model; %end; proc sort data=step_&var; by parm; proc sort data=pval; by parm; data step_&var; merge step_&var pval; by parm; p&i=put(ProbChiSq, pvalue6.3); drop ProbChiSq ChiSq DF; run; proc sql noprint; select max(ProbChiSq) into :pmax from pval; select distinct parm into :varlist separated by ' ' from pval having ProbChiSq^=max(ProbChiSq); quit; %let i=%eval(&i+1); %end; proc print data=step_&var; title "&var: model selection process"; run; %mend MdSelect;

這個調整過後的程式將可以更有彈性。

CONTACT INFORMATION
Your comments and questions are valued and encouraged. Contact the authors at:
Jing Su
Merck & Co., Inc.
UG1D-88
Po Box 1000
North Wales, PA 19454-1099
Work Phone: 267-305-6949
Email: jing_su@merck.com

Wei (Lisa) Lin
Merck & Co., Inc.
UG1D-88
Po Box 1000
North Wales, PA 19454-1099

沒有留言:

張貼留言

要問問題的人請在文章下方的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; }