BookmarkSubscribeRSS Feed

In a simple stacked bar chart, such as on a graph like such: proc sgplot data=sashelp.prdsale; vbar year/response=actual group=quarter groupdisplay=stack; run; It is often desired to have the response value labeled on each stacked bar.  This can be done with annotation, but it is cumbersome and causes difficulty when using SGPANEL (for example) to combine multiple charts.  Currently, datalabels create tables on top or bottom when used with stacked bar charts, but do not overlay the groups.  Instead doing this: proc sgplot data=sashelp.prdsale; vbar year/response=actual group=quarter groupdisplay=stack datalabel datalabelpos=center; run; or something like that would be simple, and as the data tip already contains this information, this should not be complex to implement.

12 Comments
AncaTilea
Pyrite | Level 9

I just had to create a stacked bar and needed the labels to be centered.

SGPLOT wouldn't allow it.(or I am not aware of it)

So I went back to annotate/gchart - but needed to calculate the mid-point using the high/low values for each subgroup.

Jay54
Meteorite | Level 14

Yes, this would be something we can add in future release.  It was considered that such labeling would lead to a cluttered graph, especially with short segments stacked closely.  However, if you need such a graph, and are willing to use Annotate, then there is an easier way with SGPLOT.

Summarize your data using proc MEANS by category and group.  Then, use data step to compute the low and high value for each stacked segment per category.  Now, use the HIGHLOW bar to plot each segment, and use a SCATTER with MarkerChar to overlay the labels.

I will work up an example and post in Graphically Speaking.

snoopy369
Barite | Level 11

Thanks! I've solved this for the current project by using a line plot to overlay a VBAR, actually (since Scatter can't overlay a bar graph).  If you set width=0, the line chart data labels overlay nicely, and if you are using GTL you can set the datalabelpos to data (center).  (This doesn't work in SGPLOT - I guess you haven't enabled that datalabel pos yet?)  Just would be nice to do it here (and to be able to work on unsummarized data). If you do enable it, I would definitely suggest some option for controlling when the label is shown for small bars.  Perhaps option of [show anyway]|[offset with line]|[suppress] or something like that.  I'm just removing the line segments for small bars myself.

Jay54
Meteorite | Level 14

SGPLOT VLINE will work, except you can't control the the location of the data labels.  With GTL you can overlay scatter on bar chart and control label drawing but you need to set the right position.  I agree with your suggestion that we will need some kind of DataLabelPolicy to control how the labels are drawn.

snoopy369
Barite | Level 11

Hmm.  I just tried again with scatter with barchartparm (in GTL) and had no problems with it - very confused as I rather thought it was disallowed last time I tried.  I must have tried something else that was similar but not identical 🙂  Perhaps it was in SGPANEL.  Thanks!

GraphGuy
Meteorite | Level 14

Note that with gchart annotate, rather than having to calculate the numeric coordinate of each stacked bar segment, you can just use the 'subgroup' variable, and gchart & annotate will figure it out for you Smiley Happy  Here's an example...

data my_anno; set sashelp.class;
xsys='2'; ysys='2'; when='a'; position='4';
midpoint=age; subgroup=trim(left(name));
function='label'; text=trim(left(name))||'a0'x;
run;

proc gchart data=sashelp.class anno=my_anno;
hbar age / discrete type=sum sumvar=height subgroup=name nolegend;
run;

foo.png

AncaTilea
Pyrite | Level 9

Thank you,Rob.

But not quite what I need.

The SGPLOT or the ANNOTATE/GCHART will allow for labels to be placed either above or below the line.

I needed centered labels

stacked_bar_labels.PNG

GraphGuy
Meteorite | Level 14

Ahh - ok ... that's a little more complicated, but can be done by sorting the data, and then "walking" your way through a data step, such as ...

proc sort data=sashelp.class out=my_anno;
by age name;
run;


data my_anno; set my_anno;
by age;
retain cumulative;
if first.age then cumulative=0;
cumulative+height;
midpoint=age; x=cumulative-(height/2); output;
run;


data my_anno; set my_anno;
xsys='2'; ysys='2'; when='a'; position='5';
function='label'; text=trim(left(name));
run;


proc gchart data=sashelp.class anno=my_anno;
hbar age / discrete type=sum sumvar=height subgroup=name nolegend;
run;

foo.png

AncaTilea
Pyrite | Level 9

Yes.

I did that Smiley Happy

I have already created the plot attached. I was merely mentioning that there is a bit of calculations (which I enjoy) to figure out the position.

Smiley Happy

snoopy369
Barite | Level 11

Is there a way to mark this idea completed or something like that? 

This was added in SAS 9.4 M2.  Thanks Sanjay and team for being responsive and adding this useful feature!