data cholesterol (index=(deathcause)); set sashelp.heart; where deathcause ne '' and cholesterol ne .; keep deathcause cholesterol; run; * output summary statistics of interest in wide format with var names corresponding to those needed for parameter based box plot; proc means data=cholesterol p5 p25 p50 p75 p95 mean noprint; by deathcause; var cholesterol; output out = chol_sumstat (drop = _type_ _freq_) min(cholesterol)=Outlier p5(cholesterol)=Min q1(cholesterol)=Q1 median(cholesterol)=Median mean(cholesterol)=Mean q3(cholesterol)=Q3 p95(cholesterol)=Max max(cholesterol)=FarOutlier; *ods output summary = chol_sumstat_wide; run; * convert summary statistics to long format for parameter based boxplot; proc transpose data = chol_sumstat out = chol_sumstat_long (rename=(_name_=SumStat Col1 = SumStat_Value)) ; by deathcause; var _numeric_; run; * kde stands for kernel desnity estimation and the procedure does just that; proc kde data = cholesterol ; by deathcause; univar cholesterol(gridl=100 gridu=500) / NGRID=401 unistats percentiles plots=none /*(plots=(density HISTDENSITY)*/ out = chol_dens (rename=(value=cholesterol) drop=var); run; * stack density and summary stat datasets; * include ridiuclous cludge to add additional quantile markers to parameter based box plot - create new vars that declare quantile of interest the median - boxplotparm needs a q1 and q3 in stat variable so add phony ones, using outlier and faroutlier for convenient ordering - declare all 'missing' stat records to be filler, since boxplotparm won't run with empty stat cells; data chol_striprep; set chol_dens chol_sumstat_long; label SumStat = 'SumStat'; if SumStat='Min' then SumStat_P5 = 'Median'; else if SumStat='Q1' then SumStat_Q1 = 'Median'; else if SumStat='Q3' then SumStat_Q3 = 'Median'; else if SumStat='Max' then SumStat_P95 = 'Median'; else if SumStat = 'Outlier' then do SumStat_P5 = 'Q1'; SumStat_Q1 = 'Q1'; SumStat_Q3 = 'Q1'; SumStat_P95 = 'Q1'; end; else if SumStat = 'FarOutlier' then do SumStat_P5 = 'Q3'; SumStat_Q1 = 'Q3'; SumStat_Q3 = 'Q3'; SumStat_P95 = 'Q3'; end; array Cludge(5) $ SumStat SumStat_P5 SumStat_Q1 SumStat_Q3 SumStat_P95; do i = 1 to 5; if Cludge(i) = '' then Cludge(i) = 'Filler'; end; drop i; run; %let gpath='C:\'; %let dpi=200; ods html close; ods listing gpath=&gpath image_dpi=&dpi style=htmlblue; *ods graphics / width=6in height=4in imagename='DensityStrip'; proc template; define statgraph DensityStripOverlay; begingraph; rangeattrmap name='map'; range min-max / rangecolormodel=(white cx445694); *cx3182BD; endrangeattrmap; rangeattrvar var=density attrvar=density attrmap='map'; entrytitle 'Cholesterol Density Strip'; layout overlay / xaxisopts=(label='Cholesterol' linearopts=(tickvaluesequence= (start=100 end=500 increment=50) viewmax=500)) yaxisopts=(display=(tickvalues)); heatmapparm x=cholesterol y=deathcause colorresponse=density / xbinaxis=false ygap=5px colormodel=TWOCOLORRAMP name="heatmapparm"; boxplotparm y=SumStat_Value x=deathcause stat=SumStat / orient=horizontal boxwidth=.8 capshape=line DISPLAY=(caps mean median) meanattrs=(color=magenta symbol=diamondfilled size=2) MEDIANATTRS=(color=black) OUTLINEATTRS=(thickness=0) WHISKERATTRS=(thickness=0) ; * additional boxplotparms to add marker lines to other quantiles; boxplotparm y=SumStat_Value x=deathcause stat=SumStat_P5 / orient=horizontal boxwidth=.8 capshape=line DISPLAY=(caps median) MEDIANATTRS=(color=black pattern=3) OUTLINEATTRS=(thickness=0) WHISKERATTRS=(thickness=0) ; boxplotparm y=SumStat_Value x=deathcause stat=SumStat_Q1 / orient=horizontal boxwidth=.8 capshape=line DISPLAY=(caps median) MEDIANATTRS=(color=black pattern=shortdash) OUTLINEATTRS=(thickness=0) WHISKERATTRS=(thickness=0) ; boxplotparm y=SumStat_Value x=deathcause stat=SumStat_Q3 / orient=horizontal boxwidth=.8 capshape=line DISPLAY=(caps median) MEDIANATTRS=(color=black pattern=shortdash) OUTLINEATTRS=(thickness=0) WHISKERATTRS=(thickness=0) ; boxplotparm y=SumStat_Value x=deathcause stat=SumStat_P95 / orient=horizontal boxwidth=.8 capshape=line DISPLAY=(caps median) MEDIANATTRS=(color=black pattern=3) OUTLINEATTRS=(thickness=0) WHISKERATTRS=(thickness=0) ; *continuouslegend "heatmapparm" / location=outside; endlayout; endgraph; end; run; ods graphics / reset noborder width=5in height=2in imagename='DensityStripOverlay'; proc sgrender data=chol_striprep template=DensityStripOverlay; run;