dm 'clear log'; dm 'clear output'; goptions reset=all; options symbolgen macrogen mprint; ***************************************************************************; * Program: Annoaro4.sas *; * Function: To place annotated arrows and labels on gplots *; * 1. Take values including the positive and negative value *; * to determine whether the arrow goes from above the line *; * or below the line. The variable updown allows for this *; * capability. *; * 2. Run Proc Means to get the minimum and maximum values *; * 3. Add factors to the mean and max values to make space *; * for the annotation *; * 4. Draw the arrowheads using the annotate facility *; * 5. Combine the annotate values with the gplot values and *; * plot the extra values as an overlay so the annotation *; * will appear on the graph *; * Assumptions 1. X and Y variables are numeric *; * 2. X variable is called XVAR *; * 3. Y variable is called YVAR *; * 4. Variable to determine direction of arrow is UPDOWN *; ***************************************************************************; * Set up the values *; * Tailclr - color of the 'tail' of the arrow *; * Tailsize - the thickness of the 'tail' *; * Taillen - length of the tail *; * Headline - color of the outline of the arrow head *; * Headbord - thickness of the outline of the arrow head *; * Headwid - the width of the arrow head itself *; * Headsize - the length of the arrow head *; * Labelclr - color of the interior of the arrowhead *; * Labelsiz - the size of the labels *; ***************************************************************************; title 'Arrow Example with GPLOT'; data setup; tailclr='cyan'; /* color of the tail */; tailsize=4; /* thickness of the tail */; taillen=.50; /* length of the tail */; headline='red'; /* color of the arrow head outline */; headbord=2; /* thickness of the arrow head outline */; headwid=.03; /* width of the arrow head */; headfill='yellow'; /* color of the interior of the arrow head */; headsize=.20; /* length of the arrow head */; labelclr='magenta'; /* color of the label of the variable */; labelsiz=1; /* size of the label */; call symput('tailclr',tailclr); call symput('tailsize',tailsize); call symput('taillen',taillen); call symput('headline',headline); call symput('headbord',headbord); call symput('headfill',headfill); call symput('headwid',headwid); call symput('headsize',headsize); call symput('labelclr',labelclr); call symput('labelsiz',labelsiz); data temp1; input xvar yvar mylabel $ updown; n=1; cards; -2 -200 labeln2 -1 -1 -25 labeln -1 1 100 label1 1 2 200 label2 -1 3 350 label3 1 4 450 label4 -1 5 56 label5 1 6 150 label6 -1 ; ***************************************************************************: * First we figure out the max and min variables *; ***************************************************************************; proc means n min max data=temp1; var xvar yvar; output out=limits min(xvar)=minxvar min(yvar)=minyvar max(xvar)=maxxvar max(yvar)=maxyvar ; *****************************************************************; * Once we know the limits we add some factors to increase the *; * plotting area so the annotation will always fit *; * We then merge it back into the original dataset *; *****************************************************************; data limits; set limits; n=1; minxvar=minxvar - (.10 * abs(maxxvar)); maxxvar=maxxvar + (.10 * abs(maxxvar)); minyvar=minyvar - ((3 * &taillen) * abs(maxyvar)); maxyvar=maxyvar + ((.30 + &taillen) * abs(maxyvar)); data merge1; merge temp1 limits; by n; proc print data=merge1; run; ***************************************************************************; * Some key points here. first, note the xsys and ysys are set to 2 *; * and then they are matched to the x and y variables in your data. *; * You should also note the position variable as well I change it *; * depending on the location of the x variable so the annotate label *; * does not run off the graph. See position in the annotate dictonary *; * chapter in your graph reference for more details. *; ***************************************************************************; data anno1; set merge1; length function color style $ 8 text $ 10; function ='move'; color='red'; when= 'a'; style= 'swissb'; xsys= '2'; ysys= '2'; position= '1'; x = xvar ; y = yvar ; output; tailclr="&tailclr"; tailsize=&tailsize; taillen=&taillen; headline="&headline"; headbord=&headbord; headfill="&headfill"; headwid=&headwid; headsize=&headsize; labelclr="&labelclr"; labelsiz=&labelsiz; *** arrow head of pointer *********; function='move'; x=xvar;y=yvar; output; function='poly'; x=xvar-(headwid * abs(maxxvar)); y=yvar+((headsize * abs(maxyvar))) * updown; color=headfill; style='msolid'; size=2; output; function='polycont'; x=xvar+(headwid * abs(maxxvar)); y=yvar+((headsize * abs(maxyvar)) * updown); color=headfill; output; function='polycont'; x=xvar; y=yvar; color=headfill; output; ***** draw the arrowhead outline here ****; function='move'; x=xvar;y=yvar; output; function='draw'; x=xvar-(headwid * abs(maxxvar)); y=yvar+((headsize * abs(maxyvar)) * updown); color=headline; size=headbord; output; function='move'; x=xvar-(headwid * abs(maxxvar)); y=yvar+((headsize * abs(maxyvar)) * updown); function='draw'; x=xvar+(headwid * abs(maxxvar)); y=yvar+((headsize * abs(maxyvar)) *updown); color=headline; size=headbord; output; function='move'; x=xvar;y=yvar; output; function='draw'; x=xvar+(headwid * abs(maxxvar)); y=yvar+((headsize * abs(maxyvar)) * updown); color=headline; size=headbord; output; ****** draw the tail **********; function='move'; x=xvar;y=yvar; output; function='draw'; x=xvar;y=yvar + ((taillen * abs(maxyvar)* updown)); color=tailclr; size=tailsize; when='b'; output; ****** draw the label with the arrow ********; function='label'; x=xvar; y=yvar +(taillen * abs(maxyvar)* updown); text=mylabel; size=labelsiz; style='swiss'; color=labelclr; if updown=-1 then position='8'; if updown=1 then position='2'; output; run; ***************************************************************************; * now use the annotate dataset in your gplot *; ***************************************************************************; proc gplot data=merge1 anno=anno1; plot yvar * xvar maxyvar * maxxvar minyvar * minxvar/overlay; symbol1 i=join v=star c=blue; symbol2 v=none ; symbol3 v=none ; run;