%macro EmpiricalLogitPlot(class=,cont=,data=,y=,const=0.5,yorder=formatted); /*-------------------------------------------------------------------------- Version 1.1: Update to: A macro extension of SAS Usage Note 37944 to class and continuous covariates. Plots the empirical logits defined using the NBHD/2 observed X values preceding and following each observation against the levels of a single continuous covariate, and plots the empirical logits against the levels of a single CLASS covariate. Calls the %OneClassPlot and %OneContPlot macros. class= space-separated list of CLASS effects. cont= space-separated list of continuous effects. data= name of the input data set. y= name of the response variable. const= small value in case of zero cells. yorder= determine order of response levels (as done by ORDER= in PROC FREQ). Specify as needed to make the response levels appear in logical order in the Response Profile table. --------------------------------------------------------------------------*/ %let _options = %sysfunc(getoption(notes)); options nonotes; %if &data= or %sysfunc(exist(&data)) ne 1 %then %do; %put ERROR: DATA= data set not specified or not found.; %goto exit; %end; %let status=ok; %let dsid=%sysfunc(open(&data)); %if &dsid %then %do; %if %quote(&y)= %then %do; %put ERROR: The Y= option is required.; %let status=input_err; %end; %else %if %sysfunc(varnum(&dsid,%upcase(&y)))=0 %then %do; %put ERROR: Y= variable &y not found.; %let status=input_err; %end; %let rc=%sysfunc(close(&dsid)); %if &status=input_err %then %goto exit; %end; %else %do; %put ERROR: Could not open DATA= data set.; %goto exit; %end; ods exclude all; proc freq nlevels data=&data order=&yorder; where not missing(&y); table &y / out=ylevs; ods output nlevels=numy; run; ods select all; data _null_; set numy; call symputx('numy',nlevels); run; %let num=1; %let numc=0; %let numd=0; %let totnum=1; %let doClass=1; %let numym1=%eval(&numy-1); %let var=%scan(&class,&num); %if (&var=) %then %do; %let doClass=0; %let var=%scan(&cont,&num); %if (&var=) %then %goto stopit; %end; data tempdata; set &data; run; %let dsid=%sysfunc(open(tempdata)); %if &dsid %then %do; %let varnum=%sysfunc(varnum(&dsid,&y)); %if %sysfunc(vartype(&dsid,&varnum))=C %then %do; %let rc=%sysfunc(close(&dsid)); %CtoN(data=tempdata,var=&y,out=tempdata,order=&yorder,options=noformat) %end; %else %do; %let rc=%sysfunc(close(&dsid)); data _null_; set ylevs nobs=nlev; call symputx(cats('l',_n_),&y); run; data tempdata; set tempdata; select (&y); %do i=1 %to &numy; when (&&l&i) &y = &i; %end; otherwise &y = .; end; run; %end; %end; data ylevs; set ylevs; ov=_n_; label ov="Ordered Value (O.V.)"; run; proc print data=ylevs label noobs; var ov &y; title "Response Profile"; run; title; %do %while(&var ne); data tempa(keep=&y &var); set tempdata; %if %eval(&doClass eq 1) %then %do; %OneClassPlot(data=tempa,x=&var,y=&y,numy=&numy,const=&const,plot=0); %let numc= %eval(&numc+1); data tempc; set %if %eval(&numc ne 1) %then tempc; temp2; run; %end; %else %do; %OneContPlot(data=tempa,x=&var,y=&y,numy=&numy,const=&const,plot=0); %let numd= %eval(&numd+1); data tempd; set %if %eval(&numd ne 1) %then tempd; temp2; run; %end; %let num=%eval(&num+1); %let totnum=%eval(&totnum+1);; %if %eval(&doClass eq 1) %then %do; %let var=%scan(&class,&num); %if (&var=) %then %do; %let doClass=0; %let num=1; %end; %end; %if %eval(&doClass eq 0) %then %do; %let var=%scan(&cont,&num); %if (&var=) %then %goto stopit; %end; %end; %stopit: ; %if %eval(&numc>0) %then %do; proc sort data=tempc; by group x; %end; %if %eval(&numd>0) %then %do; proc sort data=tempd; by group x; %end; %if %eval(&numc>0 and &numd>0) %then %do; data tempall; merge tempd tempc; by group x; %end; %else %if %eval(&numc>0) %then %do; data tempall; set tempc; %end; %else %do; data tempall; set tempd; %end; proc sort data=tempall; by group; data tempa(keep=group minx maxx); set tempall; by group; retain minx 1e100 maxx -1e100; if first.group then do; minx=x; maxx=x; end; minx=min(minx,x); maxx=max(maxx,x); if last.group then output; data tempall; merge tempall tempa; by group; x=(x-minx)/(maxx-minx); %if ((&totnum-1)=1) %then %do; %let rows=1; %let cols=1; %end; %else %if ((&totnum-1)=2) %then %do; %let rows=1; %let cols=2; %end; %else %if ((&totnum-1)=3) %then %do; %let rows=1; %let cols=3; %end; %else %if ((&totnum-1)=4) %then %do; %let rows=2; %let cols=2; %end; %else %if ((&totnum-1)<=6) %then %do; %let rows=2; %let cols=3; %end; %else %if ((&totnum-1)<=9) %then %do; %let rows=3; %let cols=3; %end; %else %if ((&totnum-1)<=12) %then %do; %let rows=3; %let cols=4; %end; %else %do; %let rows=ceil((&totnum-1)/&cols); %let cols=5; %end; ods graphics / loessmaxobs=10000 antialiasmax=100000; proc sgpanel data=tempall; panelby group / novarname columns=&cols rows=&rows uniscale=all; rowaxis label='Empirical Cumulative Logits'; colaxis display=(nolabel noticks novalues); %if (&numd>0) %then %do i=1 %to &numym1; loess y=d&i x=x / smooth=0.3 legendlabel="&y<=&i" name="series&i" lineattrs=GraphData&i(thickness=3px) markerattrs=GraphDataDefault(color=gray); %end; %if (&numc>0) %then %do i=1 %to &numym1; series y=c&i x=x / legendlabel="O.V.<=&i" name="series&i" lineattrs=GraphData&i(thickness=3px); %end; keylegend %do i=1 %to &numym1; "series&i" %end;; title "Empirical Cumulative Logits"; title2 "for ordered values of &y against predictors"; run; %exit: options &_options; title; %mend; %macro OneClassPlot(data=dsname,x=x,y=y,numy=3,const=0,plot=1); /*-------------------------------------------------------------------------- A macro version of SAS Usage Note 37944 for CLASS covariates. Plots the empirical logits of Y against the levels of one CLASS variable X. Called by the %EmpiricalLogitPlot macro. data= name of the input data set. x= name of the single CLASS covariate. y= name of the response variable. numy= number of levels of the response. const= small value in case of zero cells. plot= 1=create the plot --------------------------------------------------------------------------*/ ods graphics / antialiasmax=100000; %let numym1=%eval(&numy-1); proc freq data=&data noprint; table &x*&y / sparse out=temp2; run; proc sort data=temp2; by &x; run; %let dsid=%sysfunc(open(temp2)); %if &dsid %then %do; %let varnum=%sysfunc(varnum(&dsid,&x)); %if %sysfunc(vartype(&dsid,&varnum))=C %then %do; %let rc=%sysfunc(close(&dsid)); %CtoN(data=temp2,var=&x,out=temp2,options=noformat) %end; %let rc=%sysfunc(close(&dsid)); %end; proc transpose data=temp2 out=temp; by &x; var count; run; data temp2 ; set temp; length group $ 32;*$; if (_NAME_='COUNT'); group="&x"; x=&x; const=%sysevalf(&const+0); %do i=1 %to &numym1; %let j=%eval(&i+1); c&i=log((sum(of col1-col&i)+const) / (sum(of col&j-col&numy)+const)); label c&i="Pr(&y <= &i)"; %end; keep c1-c&numym1 group x; run; %if %eval(&plot eq 1) %then %do; proc sgplot; %do i=1 %to &numym1; series y=c&i x=x/ lineattrs=(thickness=3px); %end; yaxis values=(-5 to 5) label="Cumulative Probability"; xaxis integer label="&x"; run; %end; %mend; %macro OneContPlot(data=dsname,x=x,y=y,numy=3,const=0.5,nbhd=50,plot=1); /*-------------------------------------------------------------------------- A macro extension of SAS Usage Note 37944 to continuous covariates. Plots the empirical logits defined using the NBHD/2 observed X values preceding and following each observation against the levels of a single continuous var, then smooths the result. Called by the %EmpiricalLogitPlot macro. data= name of the input data set. x= name of the single continuous covariate. y= name of the response variable. y=1,2,3... numy= number of levels of the response. const= small value in case of zero cells. nbhd= total number of neighbors. plot= 1=create the plot --------------------------------------------------------------------------*/ ods graphics / antialiasmax=100000; data temp; set &data; proc sort data=temp; by &x &y; %let Full=%eval(&nbhd); %let Fullp1=%eval(&nbhd+1); %let Half=%eval(&nbhd/2); %let numym1=%eval(&numy-1); data temp2; set temp; retain %do i=1 %to &numy; sum&i %end; 0; lagx= lag&Full(&x); lagHalfx=lag&Half(&x); lagy=lag&Fullp1(&y); %do i=1 %to &numy; sum&i=sum&i+(&y=&i); %end; if (lagy^=.) then do; %do i=1 %to &numy; sum&i=sum&i-(lagy=&i); %end; end; data temp; set temp2; if (_n_<&Full) then delete; data temp2; set temp; length group $ 32;*$; const=%sysevalf(&const+0); x=lagHalfx; group="&x"; %do i=1 %to &numym1; %let j=%eval(&i+1); d&i=log((sum(of sum1-sum&i)+const) / (sum(of sum&j-sum&numy)+const)); %end; keep d1-d&numym1 group x; run; %if %eval(&plot eq 1) %then %do; proc sgplot; %do i=1 %to &numym1; loess y=d&i x=x / smooth=0.2 legendlabel="Pr(&y<=&i)" lineattrs=GraphData&i(thickness=3px) markerattrs=(color=gray); %end; yaxis values=(-5 to 5) label="Cumulative Probability"; keylegend %do i=1 %to &numym1; "series&i" %end;; run; %end; %mend;