I would like the portion of the bars for home campus to be in the same position for all bars. It is hard to read when one is on the bottom and next is on the top. I want the bars to be in descending order. Thanks...
Here is the code:
proc sgplot data=zfive_year2x;
by cawardx;
where count1fifth not = .;
styleattrs datacolors=(blue red);
vbar acadplan / response=count1fifth group=home_campus
categoryorder=respdesc
outlineattrs=(color=black);
label acadplan='Academic Plan'
cawardx='Award Level'
count1fifth='Number of Students';
format cawardx $awardc.;
title1 'Chart 3: Annual Five-Year Mean Headcount Enrollment';
run;
Let's simplify the problem by getting rid of the BY statement.
The problem is that the CATEGORYORDER= option is going to order ALL the bars in a stacked bar , even those that are stacked. You say you do not want this, so we need to get rid of the CATEGORYORDER= option and instead order the categories by using VALUES= option on the XAXIS statement. There are several substeps:
I have created some fake data that seems to be similar to the first few categories in your example:
data Have;
length home_campu $6;
input acadplan $ count1fifth home_campus $;
datalines;
155 128 CHSTR
155 9 MIDLO
156 150 MIDLO
156 90 CHSTR
480 99 MIDLO
480 87 CHSTR
212 97 CHSTR
212 64 MIDLO
299 120 CHSTR
299 92 MIDLO
464 135 CHSTR
464 25 MIDLO
;
/* order the categories by frequency. Write to data set. */
proc freq data=Have order=freq;
tables acadplan / out=FreqOut;
weight count1fifth;
run;
/* read the ordered list of categories into a macro variable */
proc sql noprint;
select acadplan into :TickList separated by ' '
from FreqOut;
quit;
%put &=TickList;
/* create a stacked bar chart. Use the VALUES= option on the XAXIS statement
to order the bars by height */
title1 'Chart 3: Annual Five-Year Mean Headcount Enrollment';
proc sgplot data=Have;
vbar acadplan / response=count1fifth group=home_campus
attrid=TestAttr
outlineattrs=(color=black);
xaxis values=(&TickList);
label acadplan='Academic Plan'
count1fifth='Number of Students';
run;
My solution doesn't work with a BY statement because it relies on calling PROC FREQ and reordering the XAXIS. However, you can take my solution and wrap it in a %DO macro or use the DATA step and CALL EXECUTE to add in the BY-group processing.
Your option categoryorder=respdesc is forcing the group with the largest value as the first (bottom) value so you need to remove that to have a chance of getting the appearance you want.
Generally the first thing I try when I want a specific order is to sort the data set by the categories.
Typically the "first" element that gets set for a plot is the first value found.
I tried that thinking like you did, but the procedure ignores the order in the dataset and orders the bars by the y-axis data. I want the bars to be ordered in ascending by the response value.
Let's simplify the problem by getting rid of the BY statement.
The problem is that the CATEGORYORDER= option is going to order ALL the bars in a stacked bar , even those that are stacked. You say you do not want this, so we need to get rid of the CATEGORYORDER= option and instead order the categories by using VALUES= option on the XAXIS statement. There are several substeps:
I have created some fake data that seems to be similar to the first few categories in your example:
data Have;
length home_campu $6;
input acadplan $ count1fifth home_campus $;
datalines;
155 128 CHSTR
155 9 MIDLO
156 150 MIDLO
156 90 CHSTR
480 99 MIDLO
480 87 CHSTR
212 97 CHSTR
212 64 MIDLO
299 120 CHSTR
299 92 MIDLO
464 135 CHSTR
464 25 MIDLO
;
/* order the categories by frequency. Write to data set. */
proc freq data=Have order=freq;
tables acadplan / out=FreqOut;
weight count1fifth;
run;
/* read the ordered list of categories into a macro variable */
proc sql noprint;
select acadplan into :TickList separated by ' '
from FreqOut;
quit;
%put &=TickList;
/* create a stacked bar chart. Use the VALUES= option on the XAXIS statement
to order the bars by height */
title1 'Chart 3: Annual Five-Year Mean Headcount Enrollment';
proc sgplot data=Have;
vbar acadplan / response=count1fifth group=home_campus
attrid=TestAttr
outlineattrs=(color=black);
xaxis values=(&TickList);
label acadplan='Academic Plan'
count1fifth='Number of Students';
run;
My solution doesn't work with a BY statement because it relies on calling PROC FREQ and reordering the XAXIS. However, you can take my solution and wrap it in a %DO macro or use the DATA step and CALL EXECUTE to add in the BY-group processing.
Thanks Rick.
I believe SAS/Graph Proc Gchart is built to do exactly what you want (including the 'by' groups), without needing any extra processing, etc...
data Have;
length home_campu $6;
input acadplan $ count1fifth home_campus $;
datalines;
155 128 CHSTR
155 9 MIDLO
156 150 MIDLO
156 90 CHSTR
480 99 MIDLO
480 87 CHSTR
212 97 CHSTR
212 64 MIDLO
299 120 CHSTR
299 92 MIDLO
464 135 CHSTR
464 25 MIDLO
;
data Have; set Have;
label cawardx='Award Level';
cawardx='AAS';
run;
axis1 label=(a=90 "Number of Students") order=(0 to 250 by 50) minor=none;
axis2 label=('Academic Plan');
pattern1 v=s c=red;
pattern2 v=s c=blue;
title1 "Chart 3: Annual Five-Year Mean Headroll Enrollment";
proc gchart data=Have;
by cawardx;
vbar acadplan / sumvar=count1fifth descending subgroup=home_campus
raxis=axis1 maxis=axis2 width=5;
Are you ready for the spotlight? We're accepting content ideas for SAS Innovate 2025 to be held May 6-9 in Orlando, FL. The call is open until September 25. Read more here about why you should contribute and what is in it for you!
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.