%macro select(version, data=_last_, out=BestMods, response=, model=, class=, include=0, link=LOGIT, binwidth=1e-6, freq=, weight=, choose=AUC, method=STEPWISE, sle=.05, sls=.05, modelopts=, details=, best=max ); %let time = %sysfunc(datetime()); %let _version=1.0; %if &version ne %then %put SELECT macro Version &_version; %if &data=_last_ %then %let data=&syslast; %let opts = %sysfunc(getoption(notes)); %if &version ne debug %then %str(options nonotes;); /* -------------- Check for newer version -------------- */ %if %sysevalf(&sysver >= 8.2) %then %do; %let _notfound=0; filename _ver url 'http://ftp.sas.com/techsup/download/stat/versions.dat' termstr=crlf; data _null_; infile _ver end=_eof; input name:$15. ver; if upcase(name)="&sysmacroname" then do; call symput("_newver",ver); stop; end; if _eof then call symput("_notfound",1); run; %if &syserr ne 0 or &_notfound=1 %then %put &sysmacroname: Unable to check for newer version; %else %if %sysevalf(&_newver > &_version) %then %do; %put &sysmacroname: A newer version of the &sysmacroname macro is available.; %put %str( ) You can get the newer version at this location:; %put %str( ) http://support.sas.com/ctx/samples/index.jsp; %end; %end; /* -------------------- Check inputs -------------------- */ /* DATA= must be specified and data set must exist */ %if &data= or %sysfunc(exist(&data)) ne 1 %then %do; %put ERROR: DATA= data set not specified or not found.; %goto exit; %end; /* Verify RESPONSE= is specified */ %if %quote(&response)= %then %do; %put ERROR: The RESPONSE= option is required.; %goto exit; %end; /* Verify MODEL= is specified */ %if %quote(&model)= %then %do; %put ERROR: The MODEL= option is required.; %goto exit; %end; /* Verify CHOOSE= */ %if %upcase(&choose)=SC %then %let choose=BIC; %if %upcase(&choose) ne AUC and %upcase(&choose) ne AIC and %upcase(&choose) ne BIC and %upcase(&choose) ne RSQUARE and %upcase(&choose) ne RSQUARE_RESCALED %then %do; %put ERROR: CHOOSE= must be AUC, AIC, BIC, RSQUARE, or RSQUARE_RESCALED.; %goto exit; %end; /* Verify METHOD= */ %if (%upcase(%substr(&method,1,1)) ne F and %upcase(%substr(&method,1,1)) ne B and %upcase(%substr(&method,1,1)) ne S) or %upcase(&method)=SCORE %then %do; %put ERROR: METHOD= must be FORWARD, STEPWISE, or BACKWARD.; %goto exit; %end; /* Verify SLE= is valid */ %if %sysevalf(&sle<0) or %sysevalf(&sle>1) %then %do; %put ERROR: The SLE= value must be between 0 and 1.; %goto exit; %end; /* Verify SLS= is valid */ %if %sysevalf(&sls<0) or %sysevalf(&sls>1) %then %do; %put ERROR: The SLS= value must be between 0 and 1.; %goto exit; %end; /* Verify BINWIDTH= is valid */ %if %sysevalf(&binwidth<0) or %sysevalf(&binwidth>=1) %then %do; %put ERROR: The BINWIDTH= value must be between 0 and 1.; %goto exit; %end; /* Verify INCLUDE= is valid */ %if %sysevalf(&include<0) or %sysfunc(mod(&include,1)) ne 0 %then %do; %put ERROR: The INCLUDE= value must be an integer value 0 or greater.; %goto exit; %end; %if %upcase(&link)=GLOGIT and %upcase(&choose)=AUC %then %do; %put ERROR: With LINK=GLOGIT, CHOOSE= must be RSQUARE or RSQUARE_RESCALED.; %goto exit; %end; %let nosteps=0; /* ------------------- Fit models and collect statistics -------------------- */ ods exclude all; %if %index(%upcase(&details),SUMMARY) ne 0 %then ods select modelbuildingsummary;; %if %index(%upcase(&details),ALL) ne 0 %then ods select all;; proc logistic data=&data; %if &freq ne %then %str(freq &freq;); %if &weight ne %then %str(weight &weight;); %if %quote(&class) ne %then %str(class &class;); model &response = &model / &modelopts selection=%upcase(%substr(&method,1,1)) sle=&sle sls=&sls details rsquare link=&link %if %upcase(&link) ne GLOGIT %then binwidth=&binwidth; %if &include ne %then include=&include; ; ods output convergencestatus=_cs fitstatistics=_fs %if %upcase(&link) ne GLOGIT %then association=_auc; rsquare=_rsq parameterestimates=_pe; run; %if &syserr>4 %then %do; %put ERROR: The SELECT macro is terminating due to errors.; %goto exit; %end; %if (&include= or &include=0) and (%upcase(%substr(&method,1,1))=F or %upcase(%substr(&method,1,1))=S) %then %do; data _null_; set _cs end=eof; if _n_=1 and eof and step=0 then do; put "SELECT: No selection steps could be taken. Terminating."; call symput("nosteps",1); end; run; %if &nosteps=1 %then %goto exit; %end; proc sort data=_pe(where=(variable ne "Intercept")) out=_effs nodupkey; by step variable; run; proc transpose data=_effs out=_mods(drop=_name_) prefix=eff; by step; var variable; run; data &out; merge _fs(where=(Criterion="AIC") keep=step Criterion InterceptAndCovariates rename=(InterceptAndCovariates=AIC)) _fs(where=(Criterion="SC") keep=step Criterion InterceptAndCovariates rename=(InterceptAndCovariates=BIC)) %if %upcase(&link) ne GLOGIT %then _auc(where=(Label2="c") keep=step label2 nvalue2 rename=(nvalue2=AUC)); _rsq(keep=step nval: rename=(nvalue1=RSquare nvalue2=RSquare_rescaled)) _mods(keep=step eff:); by step; %if %upcase(&link) ne GLOGIT %then %str(drop label2;); drop Criterion; run; proc sort data=&out; by %if %upcase(&choose) ne AIC and %upcase(&choose) ne BIC %then descending; &choose; run; ods select all; proc print data=&out(obs=&best); id &choose; var eff: step; title "The SELECT Macro"; run; %if &version ne debug %then %do; proc datasets nolist; delete _cs _fs _auc _rsq _pe _effs _mods; run; quit; %end; %exit: options &opts; title; %let time = %sysfunc(round(%sysevalf(%sysfunc(datetime()) - &time), 0.01)); %put NOTE: The SELECT macro used &time seconds.; %mend;