/*------------------------------------------------------------------* | MACRO NAME : plotmat | SHORT DESC : Create a matrix of multiple scatterplots, | may also print correlations, 45 degree lines, | and/or regression lines *------------------------------------------------------------------* | CREATED BY : Vierkant, Rob (04/09/2004 16:41) *------------------------------------------------------------------* | PURPOSE | | This macro will create a scatterplot matrix graphically | displaying the bivariate relationships between a number | of variables. The macro is similar to %SCATMAT but with | certain enhancements. | | | Authors: Rob Vierkant | email: vierknt@mayo.edu | phone: 4-8993 | | Melissa Larson | email: larson.melissa@mayo.edu | phone: 3-0937 | | Input parameters: | | %plotmat(data= dataset | varlist= names of variables, up to 10, in the matrix. | title= title of scatterplot matrix | Default is null | corr= option to print correlations with | scatterplots. Options are YES or Y, | and NO or N. Default is NO | degree45= option to print a 45 degree line on | scatterplots. Options are YES or Y, | and NO or N. Default is NO | regline= option to print a regression line on | scatterplots. Options are YES or Y, | and NO or N. Default is NO | ); | *------------------------------------------------------------------* | MODIFIED BY : Larson, Melissa (05/20/2010 15:15) | | Use standard naming process. Restore previous title information | and 3 graphics options. Simplify how the user needs to supply | list of variables for the matrix. Adding enhancements to the | graphing options. *------------------------------------------------------------------* | OPERATING SYSTEM COMPATIBILITY | | UNIX SAS v8 : | UNIX SAS v9 : YES | MVS SAS v8 : | MVS SAS v9 : | PC SAS v8 : | PC SAS v9 : *------------------------------------------------------------------* | Copyright 2010 Mayo Clinic College of Medicine. | | This program is free software; you can redistribute it and/or | modify it under the terms of the GNU General Public License as | published by the Free Software Foundation; either version 2 of | the License, or (at your option) any later version. | | This program is distributed in the hope that it will be useful, | but WITHOUT ANY WARRANTY; without even the implied warranty of | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | General Public License for more details. *------------------------------------------------------------------*/ %macro plotmat(data=,varlist=,title=,corr=N, degree45=N,regline=N); ***Local macro parameters***; %local c k i j p r totpct t lx ly uy rx llx lly ulx uly urx ury lrx lry err corr data varlist degree45 regline; ***Adjusting macro parameters and checking for errors; %let data=%upcase(&data); %let varlist=%upcase(&varlist); %let corr=%upcase(&corr); %let degree45=%upcase(°ree45); %let regline=%upcase(®line); %let err=0; %if %length(&data)=0 %then %do; %put 'ERROR: NO INPUT DATASET SUPPLIED'; %let err=1; %end; %if %length(&varlist)=0 %then %do; %put 'ERROR: NO INPUT VARLIST SUPPLIED'; %let err=1; %end; %else %do; ****count independent vars and set up macro variables var1,var2,var3...; %let numvars=0; %let var11=; %do %until(%scan(&varlist,&numvars+1,' ')= ); %let numvars=%eval(&numvars+1); %let var&numvars=%scan(&varlist,&numvars,' '); %local var&numvars; %end; %if %length(&var11)^=0 %then %do; %put 'ERROR: VARLIST HAS MORE THAN 10 VARIABLES'; %let err=1; %end; %end; %if &corr^=NO & &corr^=N & &corr^=YES & &corr^=Y %then %do; %put 'ERROR: CORR MUST BE YES OR NO'; %let err=1; %end; %if °ree45^=NO & °ree45^=N & °ree45^=YES & °ree45^=Y %then %do; %put 'ERROR: DEGREE45 MUST BE YES OR NO'; %let err=1; %end; %if ®line^=NO & ®line^=N & ®line^=YES & ®line^=Y %then %do; %put 'ERROR: REGLINE MUST BE YES OR NO'; %let err=1; %end; ****if still no errors then run correlations; %if &err=0 %then %do; ****Get variable labels; ods listing close; ods output variables=__labels; proc contents data=&data; run; ods listing; %do p=1 %to &numvars; %local local&p; data __labels; set __labels; if variable="&&var&p" then call symput("label&p",left(trim(label))); run; %local label&p; %if %length(&&label&p)=0 %then %do; %let label&p=&&var&p; %end; %put &&label&p label&p &&var&p var&p; %end; ****Store title information to reset later**; proc sql; describe table dictionary.titles; create table __titles as select number, text, type from dictionary.titles where type='T'; quit; proc sql noprint; select max(number) into: n_titles from __titles; run; %if &n_titles^= %then %do; %do r=1 %to &n_titles; data __titles; set __titles; if number=&r then call symput("__title&r",left(trim(text))); run; %put &&__title&r; %end; %end; ****Store graphics options to reset later**; proc sql; reset noprint; describe table dictionary.goptions; create table __gopts as select optname, opttype, setting, optdesc, level, group from dictionary.goptions; quit; ****generate means and correlations; proc corr data=&data out=__tmp noprint; var &varlist; run; data __tmp; set __tmp; ****create macro variables for all means; if _TYPE_='MEAN' then do; %do i=1 %to &numvars; call symput("m&i",trim(left (put(&&var&i,10.2)))); %end; end; ****create macro variables for all correlations; %do i=1 %to &numvars; if upcase(_NAME_)=upcase("&&var&i") then do; %do j=1 %to &numvars; %let k=%eval((&i-1)*&numvars+&j); call symput("c&k",trim(left (put(&&var&j,10.2)))); %end; end; %end; run; ****create annotate data sets used to place correlation on scatterplot; %if &corr=Y or &corr=YES %then %do; %do i=1 %to &numvars; %do j=1 %to &numvars; %let k=%eval((&i-1)*&numvars+&j); data __annot&k; function='label'; xsys='3'; ysys='3'; y=96; x=50; hsys='3'; size=8; style='centx'; text="correlation: &&c&k"; output; run; %end; %end; %end; ****graphic options; goptions reset=global device=xcolor nodisplay gunit=pct border rotate=landscape; ****scatterplots for the off-diagonal; symbol1 color=black %if ®line=Y or ®line=YES %then %do; interpol=R %end; value=dot height=2; symbol2 value=none color=black interpol=join height=1; axis1 label=none minor=none value=(h=3 f=simplex); axis2 label=none minor=none; proc gplot data=&data gout=__plotmat; ****title if correlation=yes is specified; title; %if &corr=Y or &corr=YES %then %do; title h=8 f=centx ' '; %end; %do i=1 %to &numvars; %do j=1 %to &numvars; %let k=%eval((&i-1)*&numvars+&j); plot &&var&i*&&var&j %if °ree45=Y or °ree45=YES %then %do; &&var&i*&&var&i %end; / vaxis=axis1 %if °ree45=Y or °ree45=YES %then %do; overlay %end; haxis=axis1 name="g&i._&j" %if &corr=Y or &corr=YES %then %do; anno=__annot&k %end; ; %end; %end; run; quit; ****variable names and means for diagonal elements; %do l=1 %to &numvars; proc gslide gout=__plotmat name="m&l"; title1 h=10 f=centx lspace=30 "&&label&l"; title2 h=10 f=centx lspace=8 "Mean=&&m&l"; run; quit; %end; ****graph for the title; proc gslide gout=__plotmat name='title'; title h=4 f=centx &title; run; quit; ****create template; goptions display; proc greplay igout=__plotmat tc=__tempcat nofs; ****assign the x and y coordinates within the template for each graph that is to be represented; tdef m&numvars %let num=%eval(&numvars-1); %if &title= %then %let totpct=100; %else %let totpct=95; %do i=0 %to # %do j=1 %to &numvars; %let t=%eval(&i*&numvars+&j); %let lx=%eval(100*(&j-1) /&numvars); %let ly=%eval(&totpct* (&numvars-&i-1)/&numvars); %let uy=%eval(&totpct* (&numvars-&i)/&numvars); %let rx=%eval(100*&j/&numvars); %let x=&t. / llx=&lx. lly=&ly. ulx=&lx. uly=&uy. urx=&rx. ury=&uy. lrx=&rx. lry=&ly; &x %end; %end; %if title^= %then %do; %let t=%eval(&t+1); %let x=&t. / llx=0 lly=0 ulx=0 uly=100 urx=100 ury=100 lrx=100 lry=0; &x %end; ; template m&numvars; ****place graphs in the boxes created for template defined above; treplay %do i=1 %to &numvars; %do j=1 %to &numvars; %let t=%eval((&i-1)*&numvars+&j; &t: %if &i=&j %then %do; m&i %end; %else %do; g&i._&j %end; %end; %end; %if title^= %then %do; %let t=%eval(&t+1); &t:title %end; ; run; quit; ****delete graphs from temporary catalogs; proc catalog c=__plotmat kill; run; quit; title; %if &n_titles^= %then %do; %do i=1 %to &n_titles; title&i "&&__title&i"; %end; %end; ****Reset graphics options; proc sql; reset noprint; describe table dictionary.goptions; create table __gopts2 as select optname, opttype, setting, optdesc, level, group from dictionary.goptions; quit; proc sort data=__gopts; by optname; run; proc sort data=__gopts2; by optname; run; data __gopts_comp; merge __gopts __gopts2(rename=(setting=setting2 opttype=opttype2)); by optname; if setting ne setting2 then diff=1; if diff=1; run; ods listing close; proc freq data=__gopts_comp; ods output onewayfreqs=__freq; tables diff; run; ods listing; data __freq; set __freq; call symput('ndiff',frequency); run; %put &ndiff; %if &ndiff^= %then %do; %do i=1 %to &ndiff; data __gopts_comp; set __gopts_comp; if _n_=&i then do; call symput('setting',left(trim(setting))); call symput('optname',left(trim(optname))); call symput('opttype',left(trim(opttype))); end; run; %put &optname &opttype &setting; %if &optname^= & &opttype^=Boolean %then %do; goption &optname=&setting; %end; %if &optname^= & &opttype=Boolean %then %do; goption &setting; %end; %end; %end; ****delete created datasets; proc datasets; delete __annot: __freq __gopts: __plotmat __tempcat __titles __tmp; quit; %end; %mend plotmat;