I have a table 'have' with the following columns.
ID
AgeGroup: 18-24, 25-29, 30-34, 35-39, 40-44, 45-49, 50-59, 60+
Gender: F, M
Race: Black, White, Hispanic, Asian, Hawiian/AmIndian, Other
Vaccination Status: Full, Partial, None
Sample table
data have;
input ID AgeGroup $ Gender $ Race $ VaccinStatus $;
datalines;
100 18-24 F Asian Full
101 25-29 M Hispanic Full
102 18-24 F White None
103 55+ M White Full
104 40-44 F Hispanic None
105 18-24 M Asian Full
106 50-54 M White Full
107 30-34 M Asian None
108 18-24 M Hispanic Full
109 40-44 M White Partial
110 45-49 M Other Full
111 55+ F Asian Full
112 40-44 M Other Partial
113 35-39 F Hawaiian Partial
114 25-29 M Asian Full
115 40-44 M Hawaiian Full
116 30-34 F White Partial
117 40-44 F White Full
118 45-49 F Asian Full
119 18-24 M Hispanic Full
120 25-29 F White None
121 55+ M White Full
122 45-49 F Hispanic None
123 50-54 M Asian Full
124 30-34 M White Full
125 40-44 M Asian None
126 18-24 M Hispanic Full
127 55+ M White Partial
128 35-39 M Other Full
129 50-54 F Asian Full
130 18-24 M Other Partial
131 35-39 F Hawaiian Partial
132 45-49 M Asian Full
133 40-44 M Hawaiian Full
134 30-34 F White Partial
135 18-24 F White Full
run;
I would like to create a 100% stacked bar chart where AgeGroup with categories, Gender with categories, Race with categories will be on the X-axis and Vaccination Status will be on the Y-axis.
I tried the following code but failed.
Proc SGPLOT data=Have pctlevel=group;
Vbar AgeGroup, Gender, Race / group = VaccinStatus Stat=percent;
Title 'Vaccination Status by Age, gender and race';
Xaxis discreteorder=data;
YAXIS grid values=(0 to 100 by 10);
run;
quit;
Error Log:
NOTE: Writing HTML5(EGHTML) Body file: EGHTML
27
28 Proc SGPLOT data=Have pctlevel=group;
29 Vbar AgeGroup, Gender, Race / group = VaccinStatus Stat=percent;
_
22
200
ERROR 22-322: Syntax error, expecting one of the following: ;, /.
ERROR 200-322: The symbol is not recognized and will be ignored.
30 Title 'Vaccination Status by Age, gender and race';
31 Xaxis discreteorder=data;
32 YAXIS grid values=(0 to 100 by 10);
33 run;
See it this gives you a starting point:
/* this is one way to carfully get values that total percentages to 100 by groups */ proc tabulate data=have out=work.tabsummary; class agegroup gender race Vaccinstatus; tables (agegroup gender race)*Vaccinstatus , pctn<Vaccinstatus> ; run; data work.toplot; set work.tabsummary ; length axisgroup axisvalue $ 10; if _type_= '1001' then do; axisgroup= 'Age Group'; axisvalue= AgeGroup; value = PctN_1000; end; if _type_= '0101' then do; axisgroup= 'Gender'; axisvalue = Gender; value = PctN_0100; end; if _type_= '0011' then do; axisgroup= 'Race'; axisvalue = race; value = PctN_0010; end; run; proc sgpanel data=work.toplot; panelby axisgroup /uniscale=row layout=columnlattice /* colheaderpos=bottom*/ novarname /* noheaderborder*/ /* noborder */ proportional ; vbar axisvalue/response=value group=Vaccinstatus ; colaxis label=' '; run;
The Proc tabulate as I have in the comments is to get the percentages such that the vaccine status percentages are calculated and total to 100 with the report group. This is not the only way but is relatively easy to expand on the number of report groups.
The data step gets a single X-axis variable and assigns the values to a single variable. Because of the way the output data set is created it also gets a single value for the different types of percentages.
This uses options available in SGPANEL to create subgraphs for each of the report groups and some options to get sort of close to your shown desired appearance. You can experiment some by removing the comment characters around some of the options in the Panelby statement.
One of the requirements across most of the graphing procedures is a single X-axis variable.
So likely need to do some data reshaping.
Can you provide some example data in the form of a working data step so we can work through to a solution using step that follow your data? If we have to make up data it is quite likely not going to resemble yours and so provided steps would be quite likely not be a workable solution for you.
Note; you should include the log with the errors you proc attempt threw. Such as
89 proc sgplot data=work.class; 90 vbar age, sex / stat=percent; - 22 200 ERROR 22-322: Syntax error, expecting one of the following: ;, /. ERROR 200-322: The symbol is not recognized and will be ignored. 91 run;
Which indicates the comma (or anything except a space or / or ; ) is going to be invalid.
Other likely attempts will get you errors like "The same category variable must be used for summarized plots"
See it this gives you a starting point:
/* this is one way to carfully get values that total percentages to 100 by groups */ proc tabulate data=have out=work.tabsummary; class agegroup gender race Vaccinstatus; tables (agegroup gender race)*Vaccinstatus , pctn<Vaccinstatus> ; run; data work.toplot; set work.tabsummary ; length axisgroup axisvalue $ 10; if _type_= '1001' then do; axisgroup= 'Age Group'; axisvalue= AgeGroup; value = PctN_1000; end; if _type_= '0101' then do; axisgroup= 'Gender'; axisvalue = Gender; value = PctN_0100; end; if _type_= '0011' then do; axisgroup= 'Race'; axisvalue = race; value = PctN_0010; end; run; proc sgpanel data=work.toplot; panelby axisgroup /uniscale=row layout=columnlattice /* colheaderpos=bottom*/ novarname /* noheaderborder*/ /* noborder */ proportional ; vbar axisvalue/response=value group=Vaccinstatus ; colaxis label=' '; run;
The Proc tabulate as I have in the comments is to get the percentages such that the vaccine status percentages are calculated and total to 100 with the report group. This is not the only way but is relatively easy to expand on the number of report groups.
The data step gets a single X-axis variable and assigns the values to a single variable. Because of the way the output data set is created it also gets a single value for the different types of percentages.
This uses options available in SGPANEL to create subgraphs for each of the report groups and some options to get sort of close to your shown desired appearance. You can experiment some by removing the comment characters around some of the options in the Panelby statement.
You can't make up syntax that does not exist.
Your graph is straight forward with proc gchart
and more difficult with ods
graphics (no doubt more advanced users can fix my attempts).
ods _all_ close;
ods pdf file="%sysfunc(pathname(WORK))/dummy.pdf";
ods output CrossTabFreqs=CROSSTABFREQS;
proc freq data=HAVE; ******* CALCULATE PERCENTAGES HERE FOR NOW, MAYBE IN GRAPHS LATER ************;
table (AGEGROUP GENDER RACE) * VACCINSTATUS ;
run;
ods output close;
ods pdf close;
data PLOT;
set CROSSTABFREQS;
where _TYPE_='11';
if AGEGROUP ne ' ' then AXISGROUP = 'Age Group';
if GENDER ne ' ' then AXISGROUP = 'Gender ';
if RACE ne ' ' then AXISGROUP = 'Race ';
AXISVALUE = coalescec(AGEGROUP, GENDER, RACE);
run;
then
proc sgplot data=PLOT; ********************** NO AXIS GROUPING ********************************;
vbar AXISVALUE / response=ROWPERCENT group=VACCINSTATUS stat=SUM groupdisplay=stack ;
xaxis display=(nolabel) discreteorder=data ;
yaxis display=(nolabel) grid values=(0 to 100 by 10);
run;
proc sgpanel data=PLOT; **************** TOO MANY BARS DESPITE nozerobars OPTION **************;
panelby AXISGROUP / onepanel layout=columnlattice colheaderpos=bottom noborder novarname;
vbar AXISVALUE / group=VACCINSTATUS response=ROWPERCENT stat=sum nozerobars groupdisplay=stack grouporder=data ;
colaxis display=(nolabel);
rowaxis display=(nolabel) values=(0 to 100 by 10) ;
run;
axis1 label=none;
goptions dev=png xpixels=800 ypixels=600;
proc gchart data=PLOT; ***************** PERFECT ************************************************;
vbar AXISVALUE / subgroup=VACCINSTATUS sumvar=ROWPERCENT group=AXISGROUP nozero raxis=axis1 maxis=axis gaxis=axis1;
run;
quit;
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.