Let me admit first of all to being new to much of graphing in SAS. I have scoured the internet, several books I bought, and the forum for help, but I can't figure out several problems I'm having. (BTW, I'm using EG 5.1, 9.3 on a Linux server.) Ultimately, I'm trying to create a fairly simple bar chart with a reference line and an (ideally) rotated text label next to the reference line. I created it first using SGRENDER but ran into a bunch of problems, so I moved to SGPLOT instead. All is working well EXCEPT I can't seem to get the annotation that produces the text label to display on the graph. I don't get any errors in the log, the annotate data set that's produced looks reasonable, but it just doesn't display.
Anyway, I realized I didn't really understand how annotation placement works, so I stepped back, read more documentation, and found an example on the web (many thanks to whoever created it!) that I used to walk through until I understood it (code is attached, including my attempts to use SGPLOT at the end). It uses GCHART, and everything works fine and produces the lines and the labels. However, when I try the exact same thing using SGPLOT, it doesn't display (again, the chart looks fine, but there's no lines or labels). I'm at my wit's end and am hoping someone can help me understand as a first step what's going on and why I'm seeing the annotation with GCHART but not SGPLOT. (FWIW, I'm using graph format=PNG as I understand other options can cause issues.)
/* Create input data set, A */
data a;
input Year Y;
datalines;
90 40
91 85
92 80
93 50
94 90
95 80
;
run;
/* Create the Annotate data set, B */
data b;
length color function $8 text $14;
retain xsys '1' ysys '2' when 'a';
function='move'; x=0; y=60; output;
function='draw'; x=100; y=60;
color='blue'; size=2; output;
function='label'; x=50; y=60; size=1.5;
position='2'; color='black'; text='Goal=60'; output;
function='move'; x=0; y=70.83; output;
function='draw'; x=100; y=70.83;
color='green'; size=2; output;
function='label'; x=50; y=70.83; size=1.5;
position='2'; color='black'; text='Avg=70.83'; output;
run;
/* Add a title to the graph */
title1 'Sales Report';
/* Define axis characteristics */
axis1 order=(0 to 100 by 25);
/* Produce the bar chart using the ANNO= */
/* option on the VBAR statement */
proc gchart data=a;
vbar year / anno=b sumvar=y raxis=axis1 discrete
width=8;
run;
quit;
proc sgplot data=a sganno=b ;
vbar year /response=Y stat=sum barwidth=.9 ;
run;
quit;
Hi Rachel,
Assuming the location of the label doesn't matter that much then you could use the refline statement along with the label option in Proc SGPLOT to draw a reference line and also label the reference. This route is a bit more easier than learning the annotation route with SGPLOT and very intuitive.
Here is an example:
proc sgplot data = a;
vbar year / response = Y stat = sum barwidth = .9;
refline 60 / axis = y lineattrs = (color = blue) label = "Goal=60";
refline 70.83 / axis = y lineattrs = (color = green) label = "Avg=70.83";
run;
You can also use the option labelloc = inside to move the labels inside of the plot.
Thank you.
Hi Rachel,
Assuming the location of the label doesn't matter that much then you could use the refline statement along with the label option in Proc SGPLOT to draw a reference line and also label the reference. This route is a bit more easier than learning the annotation route with SGPLOT and very intuitive.
Here is an example:
proc sgplot data = a;
vbar year / response = Y stat = sum barwidth = .9;
refline 60 / axis = y lineattrs = (color = blue) label = "Goal=60";
refline 70.83 / axis = y lineattrs = (color = green) label = "Avg=70.83";
run;
You can also use the option labelloc = inside to move the labels inside of the plot.
Thank you.
Given that you are trying to draw lines using annotate, the easiest way is to use the REFLINE statement as suggested by DjRisks.
FYI, the annotation data set used by SGPLOT is not the same as GCHART. Please see the SGPLOT doc for SGANNO.
Thanks for the answers, djrisks and Sanjay!
I actually am using REFLINE in my "real" program, and it works to draw the line, but I've been unable get the label to display. However, it was very helpful seeing that the REFLINE option CAN work in SGPLOT, and I went back and was able to draw a labelled refline on the Y axis of my real graph just like the example that djrisks proposed. I am still not having any luck with the real refline that I want to label, which is drawn on the X axis. Again, the line draws fine, but the label does not display. However, I think I realize now that there's something going on with placement, or collision between graph elements, that's causing the label to not display, so I'll keep working on it. At least I now know it's possible
Sanjay, I will check out the SGPLOT doc for SGANNO as you suggest - I wasn't aware it was different for SGPLOT so I'm sure that's the source of the problem. I suspect I'll ultimately have to use annotate for my label since we want rotated text, but for the interim if I can just get any sort of label for the refline I'll be happy!
You can also use REFLINE for X axis, using the AXIS=X option. Note for VBAR in SGPLOT, the X axis will be categorical (Character) even if the values are numbers. So, you will need to use the right data type for the value, and the value can only be one of the values on the axis. To position something between the tick values '92' and '93', use DISCRETEOFFSET. See attached graph.
proc sgplot data=a;
vbar year /response=Y stat=sum barwidth=.9 ;
refline '92' / axis=x discreteoffset=0.5 label="New Label" labelloc=inside;
run;
That's fine Rachael.
Just letting you know that another alternative method to display annotated text especially rotated text is to use the drawtext statement in GTL. This is similar to using SGANNO, however you can add the annotated text with one line of code, although you will need to know GTL too.
Here is an example below.
proc template;
define statgraph labels;
begingraph;
layout overlay;
barchart x = year y = y / stat = sum barwidth = .9;
referenceline y=60 / lineattrs = (color = blue) curvelabel = "Goal=60";
referenceline y=70.83 / lineattrs = (color = green) curvelabel = "Avg=70.83";
drawtext "Text" / y=65 x=93 yspace = datavalue xspace = datavalue rotate=90;
endlayout;
endgraph;
end;
run;
proc sgrender data = a template = labels;
run;
Thanks.
Once again, thanks so much for all the help from everyone. Ultimately, I discovered I had an error in the PROC FORMAT I was using to create the groups that were being used as the discrete X axis values. So, when I was trying to use this incorrect value as a label of any sort, it was failing. It's very hard to troubleshoot when you don't really understand what you're doing, so the information given in this thread was instrumental in figuring out the problem.
Once I figured out the problem, I did go back to GTL and use drawtext, which does seem easier than other methods. It is working fine, so my text is now rotated and looks great! Thanks to everyone for all the very kind help!
Just for future reference. With SAS 9.4M2, you can use the TEXTPLOT to draw text in the graph using the procedure data set. This text is data driven and axis aware, and not hard coded like DRAWTEXT, nor a post process like annotate.
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.