Reputation: 2448
I am using SAS 9.3 How can I change colors of bars in proc sgplot vbar.
This is what I want but I would like to have s2 and s5 to have different color in the plot. Preferably there should be legend as well.:
data gr;
input x $ y groupvar $;
datalines;
s1 20 a
s2 20 b
s3 30 a
s4 25 a
s5 45 b
;
run;
proc sgplot data=gr;
vbar x /response=y CATEGORYORDER=RESPDESC ;
run;
This produces what I want except now my CATEGORYORDER statement gets ignored:
proc sgplot data=gr;
vbar x /response=y group=groupvar CATEGORYORDER=RESPDESC ;
run;
Then I have also tried this but it doesn't help anything.
proc sort data=gr;
by groupvar;
run;
proc sgplot data=gr;
vbar x /response=y group=groupvar GROUPORDER = DATA;
run;
Comment: I am not sure if the group statement can help me here because it seems to be designed for the situations when there are actually all x-axis variables present in all of the groups. For example like this.
data gr;
input x $ y groupvar $;
datalines;
s1 20 a
s1 20 b
s2 30 a
s2 25 b
s3 10 a
s3 12 b
;
run;
proc sgplot data=gr;
vbar x /response=y group=groupvar GROUPDISPLAY=CLUSTER GROUPORDER = DATA;
run;
Upvotes: 1
Views: 12062
Reputation: 63424
Grouping variables aren't going to work here unless you want all the a's and all the b's together. You can't get around that with grouping variables.
You have two big picture options. One is to use attribute maps, one is to use multiple high-low charts to simulate your bar colors. I think the former is much easier, so I won't go into the latter - just keep it in mind for other possible issues; high-low chart is a more flexible version of a bar chart in many ways.
Attribute Maps are used for mapping variable values to attributes (color, pattern, etc.). You set up a dataset with id
, value
, and then fillcolor
or linecolor
or whatnot variables depending on what you're trying to change.
id
is a unique ID for each separate attribute map. Multiple attribute maps can exist in one dataset, but each id
value is one set of mappings that will be used at once - it should be based on one variable, for example. You will use the attribute map based on this value.value
is the variable value (so here, s1
s2
etc. - I don't think you can use a
and b
since you really don't want to group by them). You will instead group by x
.fillcolor
should be red
or green
or whatnot, as a character variable.Something like this:
data dattrmap;
set gr;
value=x;
length fillcolor $8;
id='xcolor';
if groupvar='a' then fillcolor='red';
else fillcolor='green';
run;
You then use it in the sgplot, something like
proc sgplot data=gr dattrmap=dattrmap;
vbar x/response=y group=x attrid=xcolor;
run;
As per the comments about the legend, you'll have to roll your own legend or do something a bit hacky to get it to work as far as I know. You can either use an INSET
(which is a text box) where you alter the color of the text (not entirely sure if this would work) or you could make a dummy plot that you don't intend to actually show (ie, you'll override it to not be visible) but it contributes the legend. GTL would do a better job of this (as you could write the legend out by hand there) but then the attribute map would be messier, so I don't know which is better.
This, for example, works, if you don't mind the hackiness. It does require VBARPARM instead of VBAR, which is fine for your data as presented. We have a second set of bars that is intentionally not shown but generates the legend.
data dattrmap;
set gr;
id='xcolor';
value=x;
length fillcolor $8;
if groupvar='a' then fillcolor='red';
else fillcolor='green';
output;
if _n_=1 then do;
id='acolor';
value='a';
fillcolor='red';
output;
value='b';
fillcolor='green';
output;
end;
run;
proc sgplot data=gr dattrmap=dattrmap noautolegend;
vbarparm category=x response=y/ group=x attrid=xcolor;
vbarparm category=x response=y/ group=groupvar barwidth=0 nooutline attrid=acolor name="forlegend" legendlabel="Groupings";
keylegend "forlegend"/ autoitemsize;
run;
Upvotes: 2