I think you need to keep the variable SEX in work.temp, and add group=sex to your scatter plots. I also added groupdisplay=cluster and clusterwidth. This is not working, but I would play with code like this:
data have;
set sashelp.heart(obs=1000);
run;
ods select none;
ods output sgplot=sgplot1;
proc sgplot data=have ;
vbox weight/group=sex category=bp_status ;
run;
ods select all;
%let dsid=%sysfunc(open(sgplot1));
%let first=%sysfunc(nliteral(%sysfunc(varname(&dsid,1))));
%let second=%sysfunc(nliteral(%sysfunc(varname(&dsid,2))));
%let third=%sysfunc(nliteral(%sysfunc(varname(&dsid,3))));
%let dsid=%sysfunc(close(&dsid));
data temp(rename=(&third.=bp_status &first.=_y &second.=_stat));
set sgplot1;
_value=round(&first.,0.01);
if not missing(&second.) and &second. in ('MIN' 'MAX' 'MEDIAN' 'MEAN' 'Q1' 'Q3');
keep _value &first. &second. &third. sex;
run;
data want;
set have temp;
if _stat in ( 'MEDIAN') then _value1=_value;
if _stat in ( 'MIN' 'MAX') then _value2=_value;
if _stat in ( 'MEAN' ) then _value3=_value;
run;
title c=black "foo";
proc sgplot data=want noautolegend ;
vbox weight/group=sex category=bp_status nomean boxwidth=0.1 groupdisplay=cluster clusterwidth=.8;
scatter x=bp_status y=_y /markerchar=_value1 labelstrip markercharattrs=(size=8) group=sex groupdisplay=cluster clusterwidth=.8;
scatter x=bp_status y=_y /markerchar=_value2 labelstrip markercharattrs=(size=8) group=sex groupdisplay=cluster clusterwidth=.8;
scatter x=bp_status y=_y /markerchar=_value3 labelstrip markercharattrs=(size=8) group=sex groupdisplay=cluster clusterwidth=.8;
scatter x=bp_status y=_value3 /markerattrs=(color=darkred symbol=circlefilled) name='mean' legendlabel='Mean' group=sex groupdisplay=cluster clusterwidth=.8;
scatter x=bp_status y=_value1 /markerattrs=(color=navy symbol=diamondfilled) name='median' legendlabel='Median' group=sex groupdisplay=cluster clusterwidth=.8;
yaxis integer;
keylegend 'mean' 'median'/AUTOITEMSIZE;
run;
title;
Thank you, this was certainly worth a shot! 🙂
So,
I've decided to go with SGPANEL and have given up on SGPLOT and got the following code going:
data have; set sashelp.heart(obs=1000); run; %macro box_plot(dsn=,x=,y=,title=); ods select none; ods output sgpanel=sgplot2; proc sgpanel data=&dsn.; panelby bp_status; vbox &y./ category=&x. ; run; ods select all; %let dsid=%sysfunc(open(sgplot2)); %let first=%sysfunc(nliteral(%sysfunc(varname(&dsid,1)))); %let second=%sysfunc(nliteral(%sysfunc(varname(&dsid,2)))); %let third=%sysfunc(nliteral(%sysfunc(varname(&dsid,3)))); %let dsid=%sysfunc(close(&dsid)); data temp(rename=(&third.=&x. &first.=_y &second.=_stat)); set sgplot2; _value=round(&first.,0.01); if not missing(&second.) and &second. in ('MIN' 'MAX' 'MEDIAN' 'MEAN' 'Q1' 'Q3'); keep _value &first. &second. &third. bp_status; run; data want; set &dsn. temp; if _stat in ( 'MEDIAN') then _value1=_value; if _stat in ( 'MIN') then _value2=_value; if _stat in ('MAX') then _value3=_value; if _stat in ( 'MEAN' ) then _value4=_value; run; title c=black "&title."; proc sgpanel data=want noautolegend ; panelby bp_status; vbox &y./category=&x. nomean boxwidth=0.2; scatter x=&x. y=_y / discreteoffset=0.2 markerchar=_value1 labelstrip markercharattrs=(size=8); scatter x=&x. y=_y /discreteoffset=0.2 markerchar=_value2 labelstrip markercharattrs=(size=8); scatter x=&x. y=_y /discreteoffset=0.2 markerchar=_value3 labelstrip markercharattrs=(size=8); scatter x=&x. y=_y /discreteoffset=0.2 markerchar=_value4 labelstrip markercharattrs=(size=8); scatter x=&x. y=_value4 /markerattrs=(color=darkred symbol=circlefilled) name='mean' legendlabel='Mean' ; scatter x=&x. y=_value1 /markerattrs=(color=navy symbol=diamondfilled) name='median' legendlabel='Median' ; keylegend 'mean' 'median'/AUTOITEMSIZE; run; title; %mend; %box_plot(dsn=have, x=sex, y=weight, title=VCSS-Score)
I greatly dislike the way the panel's output in this one as it's hard to tell what the scale is all the time:
I would like everything in one panel but what can I do??
Thank you,
J Fuchsia
I added
panelby bp_status/layout=COLUMNLATTICE;
And this seemed to fix my concerns!
You want this ?
data have;
set sashelp.heart(obs=1000);
run;
proc sort data=have;
by bp_status sex;
run;
%macro box_plot(dsn=,group=,x=,y=,title=);
ods select none;
ods output sgplot=sgplot1;
proc sgplot data=&dsn. ;
vbox &y./group=&group. category=&x. ;
run;
ods select all;
%let dsid=%sysfunc(open(sgplot1));
%let first=%sysfunc(nliteral(%sysfunc(varname(&dsid,1))));
%let second=%sysfunc(nliteral(%sysfunc(varname(&dsid,2))));
%let third=%sysfunc(nliteral(%sysfunc(varname(&dsid,3))));
%let forth=%sysfunc(nliteral(%sysfunc(varname(&dsid,4))));
%let dsid=%sysfunc(close(&dsid));
data temp(rename=(&third.=_x &first.=_y &second.=_stat &forth.=_group));
set sgplot1;
_value=round(&first.,0.01);
if not missing(&second.) and &second. in ('MIN' 'MAX' 'MEDIAN' 'MEAN' 'Q1' 'Q3');
keep _value &first. &second. &third. &forth.;
run;
data want;
set &dsn. temp;
if _stat in ( 'MEDIAN') then _value1=_value;
if _stat in ( 'MIN' 'MAX') then _value2=_value;
if _stat in ( 'MEAN' ) then _value3=_value;
run;
title c=black "&title.";
proc sgplot data=want noautolegend ;
vbox &y./group=&group. category=&x. nomean boxwidth=0.3 name='box';
scatter x=_x y=_y /group=_group groupdisplay=cluster clusterwidth=0.7 discreteoffset=0.12 markerchar=_value1 labelstrip markercharattrs=(color=black size=8) ;
scatter x=_x y=_y /group=_group groupdisplay=cluster clusterwidth=0.7 discreteoffset=0.12 markerchar=_value2 labelstrip markercharattrs=(color=black size=8) ;
scatter x=_x y=_y /group=_group groupdisplay=cluster clusterwidth=0.7 discreteoffset=0.12 markerchar=_value3 labelstrip markercharattrs=(color=black size=8) ;
scatter x=_x y=_value3 /group=_group groupdisplay=cluster clusterwidth=0.7 markerattrs=(color=darkred symbol=circlefilled) ;
scatter x=_x y=_value1 /group=_group groupdisplay=cluster clusterwidth=0.7 markerattrs=(color=navy symbol=diamondfilled) ;
yaxis integer;
legenditem name='mean' type=MARKER / label='Mean' MARKERATTRS=(color=darkred symbol=circlefilled) ;
legenditem name='median' type=MARKER / label='Median' MARKERATTRS=(color=navy symbol=diamondfilled) ;
keylegend 'mean' 'median' /AUTOITEMSIZE;
keylegend 'box'/location=inside position=ne across=1;
run;
title;
%mend;
%box_plot(dsn=have,group=sex,x=bp_status,y=weight, title=VCSS-Socre)
@JFuchsia wrote:
I tweaked the previous scale statement in the current code to this :
yaxis integer values=(0 to 500 by 10);and the scale is much better and I don't lose my plot labels (for mean, min, etc.)
however, how can I group the data by each year?
Thank you!!
Not exactly clear what sort of "group" you are looking for. The Group=variable option on the plot? But since we don't know your data or even the actual code you are running can't tell.
A separate graph for each year? That might be a BY statement. Or SGPANEL and PANELBY your year variable.
Or overlay multiple plots using different data layout.
See new post. Thank you! 🙂
SAS Innovate 2025 is scheduled for May 6-9 in Orlando, FL. Sign up to be first to learn about the agenda and registration!
Learn how use the CAT functions in SAS to join values from multiple variables into a single value.
Find more tutorials on the SAS Users YouTube channel.
Ready to level-up your skills? Choose your own adventure.