%let name=trellis; /* v9.2 option to get text size same as v9.1.3 */ /* options fontrendering=host_pixels; */ /* This is a proof-of-concept, showing how sas/graph could do a Trellis Plot. The original plot I was imitating/enhancing is on the following page: http://www.research.att.com/~rab/trellis/morris.html Note that I didn't have the actual raw data, so I just estimated the data values by looking at the plot - therefore, some of my estimated data points might not be exactly right ... but this is just a example to prove that this kind of plot can be done in sas :) Also note that this example is somewhat data-driven, but your data would have to be *very* much like this data to easily re-use this code :) It would be really neat to generalize this proof-of-concept, so that it would be totally data-driven and more flexible, and could be used with a wide variety of data. */ /* The sas/graph bars are generally in alphabetic (or numeric) order by the value of the bar label, or sorted ascending/descending by the height of the bars. To sort them in some other desired order, I've assigned numeric values to each variety of wheat -- the bars will be ordered by this numeric value. I then created this user-defined format, so that the numeric values will actually 'print' on the screen as this custom text showing the wheat variety name. I am hard-coding the user-defined format in this example, as is customarily done (there is a way to dynamically generate a user-defined format on-the-fly directly from the data itself ... to generalize this code, you'd need to do something like that). */ proc format; value barley_fmt 1=' ' 2='Trebl' 3='Wisconsin No. 38' 4='No. 457' 5='Glabron' 6='Peatland' 7='Velvet' 8='No. 475' 9='Manchuria' 10='No. 462' 11='Svansota' ; run; /* Similarly, a user-defined format for each farm/field */ proc format; value field_fmt 1='Waseca' 2='Crookston' 3='Morris' 4='University Farm' 5='Duluth' 6='Grand Rapids' ; run; /* Here is the data for the 'bar chart' -- each field has 13 obsns. The first 3 obsns are used to create the light/dark orange 'bars' onto which I will annotate the field name, and the 'colorval' (with values of 1, 2, and 3) control the light/dark orange color of the bar segments. The middle/orange bar segment is sort of like a range shown in a box plot. I have put all the values directly into the dataset, but these would ideally be calculated based on the data. The next 10 obsns are will be used to create 10 'white' bars in the horizontal bar chart. I will later use the val1932 and val1931 values to annotate round/colored markers into this white space. Notice that these white bars all have a length of 70, so they go all the way across the axis area. */ data mydata; format barnum barley_fmt.; input fieldnum barnum barlength colorval val1932 val1931; datalines; 1 1 58 1 . . 1 1 12 2 . . 1 1 70 3 . . 1 2 70 4 49 65 1 3 70 4 58 59 1 4 70 4 42 57 1 5 70 4 37 55 1 6 70 4 36 47 1 7 70 4 37 50 1 8 70 4 41 46 1 9 70 4 33 49 1 10 70 4 45 68 1 11 70 4 38 47 2 1 49 1 . . 2 1 9 2 . . 2 1 12 3 . . 2 2 70 4 42 47 2 3 70 4 35 49 2 4 70 4 34 45 2 5 70 4 26 38 2 6 70 4 25 41 2 7 70 4 32 41 2 8 70 4 32 43 2 9 70 4 33 39 2 10 70 4 30 48 2 11 70 4 20 40 3 1 40 1 . . 3 1 8 2 . . 3 1 22 3 . . 3 2 70 4 46 44 3 3 70 4 47 28 3 4 70 4 43 27 3 5 70 4 34 27 3 6 70 4 42 29 3 7 70 4 38 25 3 8 70 4 44 22 3 9 70 4 34 27 3 10 70 4 47 29 3 11 70 4 34 25 4 1 30 1 . . 4 1 9 2 . . 4 1 31 3 . . 4 2 70 4 28 36 4 3 70 4 37 38 4 4 70 4 25 43 4 5 70 4 36 42 4 6 70 4 28 32 4 7 70 4 25 39 4 8 70 4 29 24 4 9 70 4 25 25.5 4 10 70 4 24 36 4 11 70 4 26 34 5 1 21 1 . . 5 1 9 2 . . 5 1 40 3 . . 5 2 70 4 29 33 5 3 70 4 28 30 5 4 70 4 21 33 5 5 70 4 25 29 5 6 70 4 30 31 5 7 70 4 21 25 5 8 70 4 26 31 5 9 70 4 21 28 5 10 70 4 21 27 5 11 70 4 20.5 23.5 6 1 10 1 . . 6 1 10 2 . . 6 1 50 3 . . 6 2 70 4 19 28 6 3 70 4 19 33 6 4 70 4 18 31 6 5 70 4 12 27 6 6 70 4 25 33 6 7 70 4 31 21 6 8 70 4 13 18 6 9 70 4 21 31 6 10 70 4 18 23 6 11 70 4 15 30 ; run; data myanno; set mydata; length color $12 style $12 text $30 function $8; length field $15; field=put(fieldnum,field_fmt.); when='a'; hsys='3'; /* On each light/dark horizontal bar, annotate the name of the field, in a position centered 50% of the way between the min & max of the bar. */ if (colorval eq 1) then do; function='label'; ysys='2'; group=fieldnum; midpoint=barnum; xsys='1'; x=50; position='5'; text=trim(left(field)); size=1.3; output; end; length html $ 250; /* Annotate cyan/blue markers for the 1932 values I am using the 'W' character of the sas/graph software 'marker' font, which prints a ball/circle. */ if (val1932 ne .) then do; function='label'; ysys='2'; group=fieldnum; midpoint=barnum; xsys='2'; x=val1932; position='5'; text='W'; size=.9; style="marker"; color="cyan"; output; style="markere"; color="cx0000ff"; html='title='||quote( trim(left(field))||', '|| trim(left(put(barnum,barley_fmt.)))||'0d'x|| '1932 Barley Yield = '||trim(left(val1932))||' barrels/acre' ) ||' '|| 'href="trellis.htm"'; output; end; /* Annotate magenta/black markers for the 1931 values */ if (val1931 ne .) then do; function='label'; ysys='2'; group=fieldnum; midpoint=barnum; xsys='2'; x=val1931; position='5'; text='W'; size=.9; style="marker"; color="magenta"; output; style="markere"; color="black"; html='title='||quote( trim(left(field))||', '|| trim(left(put(barnum,barley_fmt.)))||'0d'x|| '1931 Barley Yield = '||trim(left(val1931))||' barrels/acre' ) ||' '|| 'href="trellis.htm"'; output; end; run; /* Specify proportions for a very tall/narrow chart */ goptions xpixels=500 ypixels=1200; filename odsout '.'; GOPTIONS DEVICE=gif; ODS LISTING CLOSE; ODS HTML path=odsout body="&name..htm" (title="SAS Trellis Plot") style=minimal gtitle gfootnote ; goptions noborder; goptions cback=white; goptions gunit=pct ftitle="arial/bold" ftext="arial/bold" htitle=2 htext=1.3; title " "; /* The first 3 colors are light orange, medium orange, light orange and are used in the first bar (which looks like a boxplot) */ pattern1 value=solid color=cxEED6AF; pattern2 value=solid color=cxEE7600; pattern3 value=solid color=cxEED6AF; /* Then, all the other bars are just white */ pattern4 value=solid color=white; axis1 label=none value=(justify=right); axis2 label=none value=none; axis3 label=('Barley Yield (bushels/acre)') order=(10 to 70 by 10) major=(height=.1) minor=none offset=(0,0); /* Since I'm custom-annotating my data markers, I don't get an automatic legend. I could annotate a legend, but in this simple case I think it's easier to use a title statement to look like a legend. */ title font=marker color=cyan height=1.5 'W' move=(-3.5,+0) font=markere color=cx0000ff 'W' font="arial/bold" color=black height=2 ' 1932 ' font=marker color=magenta height=1.5 'W' move=(-3.5,+0) font=markere color=black 'W' font="arial/bold" color=black height=2 ' 1931' ; proc gchart data=mydata anno=myanno; hbar barnum / discrete group=fieldnum type=sum sumvar=barlength subgroup=colorval maxis=axis1 gaxis=axis2 raxis=axis3 coutline=graycc /* Make all the bars touch, with no space between */ space=0 gspace=0 nostats nolegend des="" name="&name"; run; quit; ODS HTML CLOSE; ODS LISTING;