I am trying to create clustered bar graph in grey scale using patterns. I realize under FILLPATTERATTRS SAS has a restriction and only supports JOURNAL2, JOURNAL3, and MONOCHROMEPRINTER which I am using. However, I am unable to change the patterns to distinguish each bar in the cluster. Also, in the x-axis how can I create following tick values for each of the cluster. For example first cluster tick value should display >0 to <10, and next cluster should display >11 to <20 and so on. Attached zip file, any suggestion would be greatly appreciated.
1.) How can I control the display of x-axis groups. For example if I want to display in this order - Sedan, Wagon, Truck, Sports, SUV, Hybrid
There are multiple ways to control the category order on the x-axis. Default for SGPLOT is ascending alphabetical sort. You can sort the data in any way you want and request Data order by setting DISCRETEORDER=data on the XAXIS statement.
2.) Is there any workaround if I do not want to use journal2 style.
I believe you can use any style, as long as you enable the fillpatterns and supply the patterns for the style, if they are missing. Journal2 and Journal3 already include fill patterns in the style. Others do not, but you can now provide them by using the STYLEATTRS DATAFILLPATTERNS (9.4M5). Also, if using HTML, remember to change the ATTRPRIORITY=none. Instead, you can use use JOURNAL3 and provide colors in the STYLEATTRS DATACOLORS (9.4M0) list.
ods graphics / attrpriority=none;
proc sgplot data=sashelp.cars;
styleattrs datafillpatterns=(l1 x1 r1);
vbar type / response=mpg_city stat=mean group=origin groupdisplay=cluster fill fillpattern;
run;
Do you have an example of what you would like the graph to look like?
And maybe a description of your data (what variable names does it have, etc)?
Oh - I was assuming that was the graph you are currently getting (ie, what you didn't want!) 🙂
Procedure SGPLOT with Journal2 style will produce this output, with different fill patterns, one for each group value.
proc sgplot data=sashelp.cars(where=(origin ne 'Europe')) noborder;
vbar type / response=mpg_city stat=mean group=origin
groupdisplay=cluster displaybaseline=auto;
run;
Hi Sanjay,
Thanks much for the response. Couple of questions for below graph.
1.) How can I control the display of x-axis groups. For example if I want to display in this order - Sedan, Wagon, Truck, Sports, SUV, Hybrid
2.) Is there any workaround if I do not want to use journal2 style.
Thanks a lot for your response.
Best.
Another way with good old SAS/GRAPH:
pattern1 v=l5 c=black ;
pattern2 v=x5 c=black ;
axis1 order=('Sedan' 'Wagon' 'Truck' 'Sports' 'SUV' 'Hybrid');
goptions dev=png;
proc gchart data=sashelp.cars(where=(origin ne 'Europe')) ;
vbar type / sumvar=mpg_city mean group=origin maxis=axis1 patternid=group ;
run;
quit;
Please avoid attachments and add code and images inline when possible.
@sasuerrr wrote:
Hi Sanjay,
Thanks much for the response. Couple of questions for below graph.
1.) How can I control the display of x-axis groups. For example if I want to display in this order - Sedan, Wagon, Truck, Sports, SUV, Hybrid
For most consistent display of non-typical sort order as shown create a numerical variable with values in the order you want and assign a custom display format to show the desired text. If the order is based on frequency of occurrence you may be able to summarize your data and sort by decreasing frequency and use discreteorder=data for a discrete axis.
Please describe why you do not want to use Journal2. It may be that you can create a custom ods style based on journal2 that will get around what ever issue you have. But we would have to know what the issues might be. I am also not convinced that you have to use journal2 at all. Since the option FILLPATTERNATTRS is a GTL option you might share the rest of what you are attempting.
1.) How can I control the display of x-axis groups. For example if I want to display in this order - Sedan, Wagon, Truck, Sports, SUV, Hybrid
There are multiple ways to control the category order on the x-axis. Default for SGPLOT is ascending alphabetical sort. You can sort the data in any way you want and request Data order by setting DISCRETEORDER=data on the XAXIS statement.
2.) Is there any workaround if I do not want to use journal2 style.
I believe you can use any style, as long as you enable the fillpatterns and supply the patterns for the style, if they are missing. Journal2 and Journal3 already include fill patterns in the style. Others do not, but you can now provide them by using the STYLEATTRS DATAFILLPATTERNS (9.4M5). Also, if using HTML, remember to change the ATTRPRIORITY=none. Instead, you can use use JOURNAL3 and provide colors in the STYLEATTRS DATACOLORS (9.4M0) list.
ods graphics / attrpriority=none;
proc sgplot data=sashelp.cars;
styleattrs datafillpatterns=(l1 x1 r1);
vbar type / response=mpg_city stat=mean group=origin groupdisplay=cluster fill fillpattern;
run;
Here's a bit more detailed example for doing it with SAS/Graph. You can use any ods style you want, and you can specify the patterns via the pattern statements:
pattern1 v=l1 c=gray33;
pattern2 v=x1 c=gray33;
pattern3 v=r1 c=gray33;
axis1 label=none order=('Sedan' 'Wagon' 'Truck' 'Sports' 'SUV' 'Hybrid') offset=(2,2);
axis2 label=none value=none;
axis3 label=none minor=none style=0 offset=(0,0);
legend1 position=(top right inside) shape=bar(.15in,.15in) offset=(0,-3);
goptions dev=png;
title ls=1.5 "Sashelp.cars data (mean city mpg)";
proc gchart data=sashelp.cars;
vbar origin / sumvar=mpg_city type=mean nozero
subgroup=origin /* color & legend */
legend=legend1
group=type noframe
gaxis=axis1 maxis=axis2 raxis=axis3
space=0 autoref cref=graydd clipref;
run;
Thanks much Robert, Sanjay and Chris. Your suggestions were really helpful.
Cheers.
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.