Target Audience: Traditional 'SUGI Sam' SAS/Graph GChart users, who want to try out the new proc SGPLOT (in v9.2) for bar charts.
If you're a traditional SAS/Graph user, you no doubt have an arsenal of your old SAS/Graph programs that you re-use over and over, as a starting point for your new graphs, etc. And also you have certain options, techniques, and "tricks" that you are accustomed to using.
And you've heard about these new SG* procs (sgplot, sgscatter, and sgpanel), and you'd like to give them a try... Well, this paper explains some of the differences you're likely to encounter, mainly using Gchart and SGplot bar charts as an example. This will hopefully save some time you would have otherwise spent discovering the differences on your own. By seeing how the same graphics are achieved in the old/traditional SAS/Graph procs, and the new SGplot, you will hopefully be able to see the changes in coding style and "mind set" you'll need to make to easily transition between the two.
Note that this paper only covers bar chart-specific differences -- to see additional 'general' differences, see the examples towards the bottom of the following SGplot Paper.
For starters, you still use "proc xxxx data=xxxx", which is the same syntax you're familiar with, and also "hbar" and "vbar" -- there are a few other similarities, but don't get too "comfortable" and assume that all similarly-named options do the same thing in both of these procs! Many similar options have totally different names & techniques for controlling them.
Here's an example of a typical use of the traditional proc Gchart for creating bar charts:
proc gchart data=sashelp.retail; hbar year / discrete type=sum sumvar=sales nostats; run;
And here is the syntax to do a similar bar chart using the new proc SGplot. Notice that the new sgplot uses "stat=" and "response=", whereas gchart used "type=" and "sumvar=".
proc sgplot data=sashelp.retail; hbar year / stat=sum response=sales; run;
First, I create a "qtr" variable (quarter of the year, based on the date) - I then use this modified data set in both examples below...
data retail; set sashelp.retail; qtr=substr(put(date,yyq4.),3,2); run;
In proc Gchart, you can divide the bar into subgroups (stacked segments) using the subgroup= option:
proc gchart data=retail; hbar year / discrete type=sum sumvar=sales nostats subgroup=qtr; run;
In proc SGplot, the main difference is that you use the "group=" option, rather than the "subgroup=" option.
proc sgplot data=retail; hbar year / response=sales group=qtr; run;
Traditonally, in most of the Gchart charts (bar, pie, etc) you can use the inside={stat} and/or outside={stat} options to have it place a label containing a given statistic (freq, cfreq, cpercent, mean, percent, sum) inside and/or outside of the bars (or pie slices, etc). Here's an example using outside=mean.
proc gchart data=sashelp.class; vbar sex / type=mean sumvar=height width=13 outside=mean; run;
By comparison, in the SGplot bar chart, you can ony turn the 'datalabel' on/off, and it shows the value of the bar statistic outside the bar. There is no way to choose over statistics/values, and no way to put the value inside the bar.
proc sgplot data=sashelp.class; vbar sex / stat=mean response=height datalabel; run;
Proc Gchart was designed with histograms in mind, and is well suited for summarizing your data and producing a histogram - you only have to specify the number of bars you want in your histogram (via the 'levels=' option). By default, gchart would show you the numeric 'midpoint' of the range of values represented by each bar in the histogram, and you can optionally specify the 'range' option so that it will tell you the range of values (min-max) rather than just the numeric midpoint value.
proc gchart data=sashelp.iris; hbar SepalLength / type=freq nostats levels=5 range; run;
Proc SGplot doesn't really lend itself to creating gchart-like histograms easily. Even when using sgplot's "histogram" statement, you don't have the ability to specify the number of bins, or have it tell you the endpoints of the range represented by each bar, as in the gchart histograms.
You can create sgplot histograms similar to the gchart ones by "brute force" though, by using a data step and a bunch of "if/else" statements (one 'if' for each bar in the histogram), and deciding which bar (or, I call them "bucket"s) each data point falls in, and then do a frequency sgplot hbar chart with a bar for each bucket. To get the range of values to show up as the label for each bar (rather than the "bucket" number), you could use a user-defined format. That's a lot of data prep, and a lot of hard-coding... (S0531965)
proc format; value my_fmt 1='<48' 2='48<56' 3='56<64' 4='64<72' 5='>=72' ; run; data iris; set sashelp.iris; format bucket my_fmt.; label bucket='Sepal Length (mm)'; if SepalLength < 48 then bucket=1; else if SepalLength < 56 then bucket=2; else if SepalLength < 64 then bucket=3; else if SepalLength < 72 then bucket=4; else bucket=5; run; title "Proc SGplot"; proc sgplot data=iris; hbar bucket / stat=freq; run;
A grouped bar chart is one of the 'traditional' things that Proc Gchart does well. You simply add the 'group=' option, and you get a grouped bar chart. The example below uses 'group=age'.
proc gchart data=sashelp.class; vbar sex / type=mean sumvar=height group=age subgroup=sex space=0; run;
Proc SGplot isn't really geared towards a traditional 'grouped' bar chart, where all the groups are shown in the same chart. Instead, you do a 'paneled' display of multiple charts using Proc SGpanel, and each chart is shown separately, laid out in a gridded/panel display. (S0581114, S0581174)
proc sgpanel data=sashelp.class; panelby age / spacing=5; vbar sex / stat=mean response=height group=sex; run;
In this example, I'll use the following custom/subset data in both samples:
data mydata; set sashelp.stocks (where=(stock='IBM' and date>='01aug2005'd)); run;
For the traditional SAS/Graph chart, I'm using proc GBarline.
proc gbarline data=mydata; bar date / discrete type=sum sumvar=volume; plot / sumvar=close; run;
Similarly, SGplot allows you to specify data for a bar, and a line. The defaults for GBarline and SGplot are a bit different, but options could be used to make the results look pretty much the same.
proc sgplot data=mydata; vbar date / response=volume; vline date / response=close y2axis; run;
With GChart, you can use the 'errorbars=' option to show error bars (confidence intervals) on the bar chart. By default, the ERRORBAR= option uses a confidence level of 95 percent. You can specify different confidence levels with the CLM= option.
proc gchart data=sashelp.class; hbar age / discrete type=mean sumvar=height nostats errorbar=both; run;
Whereas, with SGplot you use the 'limits=' option.
proc sgplot data=sashelp.class; hbar age / stat=mean response=height limits=both; run;
Both these samples will use the following data:
data mydata; format population comma12.0; input st $ 1-2 population; year=2000; datalines; VA 7078515 NC 8049313 SC 4012012 FL 15982378 ;
As with most of the other traditional SAS/Graph Procs, Gchart supports the 'html=' option, which allows you to store standard html tags (such as href= for drilldowns, title= or alt= for charttip text, and target= to determine whether to drilldown within the same page or open a new window) in a text variable in the data set, and then point to that variable with the html= option. Since the values associated with the html tags must be in quotes, this sas variable must have quotes-within-quotes, which makes it a little tricky (... but provides a lot of flexibility).
data mydata; set mydata; length htmlvar $500; htmlvar= 'target="window2"' ||' '|| 'title='||quote( 'State: '||trim(left(st))||'0d'x||'Population: '||trim(left(put(population,comma12.0))) ) ||' '|| 'href="http://www.state.'||trim(left(lowcase(st)))||'.us"'; run; GOPTIONS xpixels=400 ypixels=400; ODS LISTING CLOSE; filename odsout '.'; ODS HTML path=odsout body="drill.htm"; proc gchart data=mydata; hbar st / type=sum sumvar=population nostats html=htmlvar des="" name="drill"; run; quit; ODS HTML CLOSE; ODS LISTING;
Similarly, SGplot allows you to store a drilldown value in a SAS text variable, and then use the 'url=' SGplot option to identify which variable. The syntax is simpler since you don't have to include the html tags, and have quotes-within-quotes in your drilldown string variable ... the trade-off being that you don't get to specify the html tags to control the charttips and drilldown window behavior.
data mydata; set mydata; htmlvar='http://www.state.'||trim(left(lowcase(st)))||'.us'; run; filename odsout '.'; ODS LISTING CLOSE; ODS HTML path=odsout body="drill.htm"; ods graphics / imagemap=yes imagename="drill" height=4in width=4in; proc sgplot data=mydata description=""; hbar st / stat=sum response=population url=htmlvar; run; quit; ods graphics off; ODS HTML CLOSE; ODS LISTING;
With Gplot, you control the bar colors via pattern statement(s).
pattern1 v=solid color=cx00ff00; proc gchart data=sashelp.retail; hbar year / discrete type=sum sumvar=sales nostats; run;
With SGplot, you use the fillattrs= option when controlling the color of all the bars - (see the example in the next section for the different technique that's used for controlling the color of individual bars or bar segments).
proc sgplot data=sashelp.retail; hbar year / stat=sum response=sales fillattrs=(color=cx00ff00); run;
In Proc Gchart, you use pattern statement to control the colors of the bar subgroup/segments ... You number the pattern statements, and the colors are "consumed" in that order, as they are assigned to the bar segments.
pattern1 v=solid color=pink; pattern2 v=solid color=cx67C8FF; proc gchart data=sashelp.class; vbar sex / discrete type=mean sumvar=height width=16 coutline=gray subgroup=sex; run;
In proc SGplot, you must modify the style, and modify the color for each "graphdata{n}".
proc template; Define style styles.mystyle; Parent=styles.default; Style graphdata1 from graphdata1 / contrastcolor=gray color=pink; Style graphdata2 from graphdata2 / contrastcolor=gray color=cx67C8FF; end; run; ods listing style=mystyle; proc sgplot data=sashelp.class description=""; vbar sex / stat=mean response=height group=sex; run;