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! 🙂
Are you ready for the spotlight? We're accepting content ideas for SAS Innovate 2025 to be held May 6-9 in Orlando, FL. The call is open until September 25. Read more here about why you should contribute and what is in it for you!
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.