/* define 'threepanel' template that displays a histogram, box plot, and Q-Q plot */ proc template; define statgraph threepanel; dynamic _X _QUANTILE _Title _mu _sigma; begingraph; entrytitle halign=center _Title; layout lattice / rowdatarange=data columndatarange=union columns=1 rowgutter=5 rowweights=(0.4 0.10 0.5); layout overlay; histogram _X / name='histogram' binaxis=false; densityplot _X / name='Normal' normal(); densityplot _X / name='Kernel' kernel() lineattrs=GraphData2(thickness=2 ); discretelegend 'Normal' 'Kernel' / border=true halign=right valign=top location=inside across=1; endlayout; layout overlay; boxplot y=_X / boxwidth=0.8 orient=horizontal; endlayout; layout overlay; scatterplot x=_X y=_QUANTILE; lineparm x=_mu y=0.0 slope=eval(1./_sigma) / extend=true clip=true; endlayout; columnaxes; columnaxis; endcolumnaxes; endlayout; endgraph; end; run; /* Macro to create a three-panel display that shows the distribution of data and compares the distribution to a normal distribution. The arguments are DSName = name of SAS data set Var = name of variable in the data set. The macro calls the SGRENDER procedure to produce a plot that is defined by the 'threepanel' template. The plot includes 1) A histogram with a normal and kernel density overlay 2) A box plot 3) A normal Q-Q plot Example calling sequence: ods graphics on; %ThreePanel(sashelp.cars, MPG_City) %ThreePanel(sashelp.iris, SepalLength) For details, see http://blogs.sas.com/content/iml/2013/05/08/three-panel-visualization/ */ %macro ThreePanel(DSName, Var); %local mu sigma; /* 1. sort copy of data */ proc sort data=&DSName out=_MyData(keep=&Var); by &Var; run; /* 2. Use PROC UNIVARIATE to create Q-Q plot and parameter estimates */ ods exclude all; proc univariate data=_MyData; var &Var; histogram &Var / normal; /* create ParameterEstimates table */ qqplot &Var / normal; ods output ParameterEstimates=_PE QQPlot=_QQ(keep=Quantile Data rename=(Data=&Var)); run; ods exclude none; /* 3. Merge quantiles with data */ data _MyData; merge _MyData _QQ; label Quantile = "Normal Quantile"; run; /* 4. Get parameter estimates into macro vars */ data _null_; set _PE; if Symbol="Mu" then call symputx("mu", Estimate); if Symbol="Sigma" then call symputx("sigma", Estimate); run; proc sgrender data=_MyData template=threepanel; dynamic _X="&Var" _QUANTILE="Quantile" _mu="&mu" _sigma="&sigma" _title="Distribution of &Var"; run; %mend;