Hello,
I have used sganno as a means to add letters of significance above figures for a long time. It works but it is exceedingly cumbersome adjusting x/y coordinates if there are many letters/bars/boxes. The letters are never equidistant or perfectly centered above whiskers and the second you change any formatting you have to begin monkeying around with x/y coordinates again. There MUST be a streamlined or more efficient way to do this. Below is code for the attached graph illustrating my point.
data have;
set sashelp.heart;
keep sex bp_status weight;
run;
ods select none;
ods output SGPanel=box ;
proc sgpanel data=have noautolegend ;
panelby sex / rows=2 columns=1 novarname uniscale=column;
vbox weight/category=BP_Status nooutliers;
run;
ods select all;
proc sort data=box;by Sex BOX_WEIGHT_X_BP_STATUS____X; run;
proc transpose data=box(where=(BOX_WEIGHT_X_BP_STATUS___ST in ('MIN' 'Q1' 'MEDIAN' 'Q3' 'MAX' ))) out=want;
by Sex BOX_WEIGHT_X_BP_STATUS____X;
var BOX_WEIGHT_X_BP_STATUS____Y;
id BOX_WEIGHT_X_BP_STATUS___ST;
run;
data want;
set want;
label=choosec(mod(_n_,4)+1,'A', 'B', 'BC', 'C');
run;
proc sgpanel data=want noautolegend ;
panelby sex / rows=2 columns=1 novarname uniscale=column;
highlow x=BOX_WEIGHT_X_BP_STATUS____X low=Q1 high=Q3/group=BOX_WEIGHT_X_BP_STATUS____X type=bar barwidth=0.4 lineattrs=(color=black);
scatter x=BOX_WEIGHT_X_BP_STATUS____X y=max/datalabel=label labelstrip datalabelpos=top datalabelattrs=(size=10) markerattrs=(size=0);
highlow x=BOX_WEIGHT_X_BP_STATUS____X low=median high=median/group=BOX_WEIGHT_X_BP_STATUS____X type=bar barwidth=0.4 lineattrs=(color=black) nofill;
highlow x=BOX_WEIGHT_X_BP_STATUS____X low=q3 high=max/group=BOX_WEIGHT_X_BP_STATUS____X lineattrs=(color=black);
highlow x=BOX_WEIGHT_X_BP_STATUS____X low=min high=q1/group=BOX_WEIGHT_X_BP_STATUS____X lineattrs=(color=black);
colaxis type=discrete;
rowaxis label=" " offsetmax=.1;
refline 150 / lineattrs=(color=crimson);
run;
The TEXT statement in SGPLOT / SGPANEL or TEXTPLOT in GTL may be the right solution for you to place text inside the graph. You could also see if the HIGHLABEL option of HIGHLOW plot can be useful for this.
data have;
set sashelp.heart;
keep sex bp_status weight;
run;
ods select none;
ods output SGPanel=box ;
proc sgpanel data=have noautolegend ;
panelby sex / rows=2 columns=1 novarname uniscale=column;
vbox weight/category=BP_Status nooutliers;
run;
ods select all;
proc sort data=box;by Sex BOX_WEIGHT_X_BP_STATUS____X; run;
proc transpose data=box(where=(BOX_WEIGHT_X_BP_STATUS___ST in ('MIN' 'Q1' 'MEDIAN' 'Q3' 'MAX' ))) out=want;
by Sex BOX_WEIGHT_X_BP_STATUS____X;
var BOX_WEIGHT_X_BP_STATUS____Y;
id BOX_WEIGHT_X_BP_STATUS___ST;
run;
data want;
set want;
label=choosec(mod(_n_,4)+1,'A', 'B', 'BC', 'C');
run;
proc sgpanel data=want noautolegend ;
panelby sex / rows=2 columns=1 novarname uniscale=column;
highlow x=BOX_WEIGHT_X_BP_STATUS____X low=Q1 high=Q3/group=BOX_WEIGHT_X_BP_STATUS____X type=bar barwidth=0.4 lineattrs=(color=black);
scatter x=BOX_WEIGHT_X_BP_STATUS____X y=max/datalabel=label labelstrip datalabelpos=top datalabelattrs=(size=10) markerattrs=(size=0);
highlow x=BOX_WEIGHT_X_BP_STATUS____X low=median high=median/group=BOX_WEIGHT_X_BP_STATUS____X type=bar barwidth=0.4 lineattrs=(color=black) nofill;
highlow x=BOX_WEIGHT_X_BP_STATUS____X low=q3 high=max/group=BOX_WEIGHT_X_BP_STATUS____X lineattrs=(color=black);
highlow x=BOX_WEIGHT_X_BP_STATUS____X low=min high=q1/group=BOX_WEIGHT_X_BP_STATUS____X lineattrs=(color=black);
colaxis type=discrete;
rowaxis label=" " offsetmax=.1;
refline 150 / lineattrs=(color=crimson);
run;
So brilliant and simple. 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 16. 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.