I do not do many bar charts, so i am a bit lost here on the basics, here is my code:
data test;
format
summary $15.
score percent6.4;
input region score;
datalines;
Summary .33
;
run;
proc sgplot data=test;
hbar score;
run;
and the output is
I am looking to do 2 thing to this that I think should be basic (but beyond what i am able to figure out).
1 - i'd like this to have the axis go to 100% so the 33% looks representative of 33%, right now it looks like 33% is 100%.
2 - i'd love for the color of the bar to change based on the value similar to a grading scale, <60% is red, 60-70% orange, 70-85% is yellow and over 85 is green. I think i can do that in proc format, but unclear how i assign the color within the hbar chart.
Your assistance is appreciated.
As you indicated, a format is useful for this task:
/* use format to defgine a discrete attribute map
https://blogs.sas.com/content/iml/2019/07/15/create-discrete-heat-map-sgplot.html
<60% is red, 60-70% orange, 70-85% is yellow and over 85 is green.
*/
proc format;
value GradeFmt
0 -< .60 = "< 60%"
.60 -< .70 = "60%-69%"
.70 -< .85 = "70%-84%"
.85 - 1.00 = "85%-100%";
run;
Then you want the bar LENGTH to depend on score, but the bar COLOR to depend on the formatted category. To use both of these at once, you need a second variable for the formatted value:
data test;
format region $15. score percent6.4 range GradeFmt.;
input region score;
range = score; /* <== new variable */
datalines;
Summary .33
;
title "Example of Bar Chart";
proc sgplot data=test;
hbar region / response=score group=score;
xaxis max=1 grid; /* <== force x axis to go up to 100% */
run;
Notice, however, that if you add more students, SAS will use colors from the current ODS style. That isn't hat you want. You want to specify which colors are associated with each formatted range of grades. To specify the colors, use a discrete attribute map:
/* Create a discrete data map that assigns a color to a grade range */
/* https://blogs.sas.com/content/iml/2019/07/15/create-discrete-heat-map-sgplot.html */
/* <60% is red, 60-70% orange, 70-85% is yellow and over 85 is green. */
data GradeAttrs; /* create discrete attribute map */
length Value $11 FillColor $15;
input raw FillColor;
Value = put(raw, GradeFmt.); /* use format to assign values */
retain ID 'GradeColors' /* name of map */
Show 'AttrMap'; /* always show all groups in legend */
datalines;
0 RED
.60 ORANGE
.70 YELLOW
.85 GREEN
;
To use the map, use the DATTRMAP= option on the PROC SGPLOT statement. Also, use the ATTRID= option on the VBAR statement. Let's add a few more students (I will use NAME instead of REGION for this example) and graph the grades:
data Class;
format Name $15. score percent6.4 range GradeFmt.;
input Name score;
range = score;
datalines;
Abbott .75
Beth .59
Carol .85
Derek .61
Ed 1.0
Felix .70
Garry .71
Harry .74
Izzy .33
Jacob .84
Ken .60
Lenora .69
Mike .99
Nancy .86
;
title "Colors According to Discrete Attribute Map";
proc sgplot data=Class dattrmap=GradeAttrs;
refline .60 .70 .85 / axis=x lineattrs=(color=blue);
hbar Name / response=score group=range attrid=GradeColors;
xaxis max=1 grid;
keylegend; /* will use the order in attribute map */
run;
Your request for the length of the bar to be 33% means that you want SCORE as a response value, not vertical axis.
Consider:
data test; format summary $15. score percent6.4; input region $ score; datalines; Summary .33 ; run; proc sgplot data=test; hbar region /response=score; xaxis label='Score' values=(0 to 1 by .25) valuesformat=percent6.; run;
Your data step does not read the region as character so a minor tweak there.
As you indicated, a format is useful for this task:
/* use format to defgine a discrete attribute map
https://blogs.sas.com/content/iml/2019/07/15/create-discrete-heat-map-sgplot.html
<60% is red, 60-70% orange, 70-85% is yellow and over 85 is green.
*/
proc format;
value GradeFmt
0 -< .60 = "< 60%"
.60 -< .70 = "60%-69%"
.70 -< .85 = "70%-84%"
.85 - 1.00 = "85%-100%";
run;
Then you want the bar LENGTH to depend on score, but the bar COLOR to depend on the formatted category. To use both of these at once, you need a second variable for the formatted value:
data test;
format region $15. score percent6.4 range GradeFmt.;
input region score;
range = score; /* <== new variable */
datalines;
Summary .33
;
title "Example of Bar Chart";
proc sgplot data=test;
hbar region / response=score group=score;
xaxis max=1 grid; /* <== force x axis to go up to 100% */
run;
Notice, however, that if you add more students, SAS will use colors from the current ODS style. That isn't hat you want. You want to specify which colors are associated with each formatted range of grades. To specify the colors, use a discrete attribute map:
/* Create a discrete data map that assigns a color to a grade range */
/* https://blogs.sas.com/content/iml/2019/07/15/create-discrete-heat-map-sgplot.html */
/* <60% is red, 60-70% orange, 70-85% is yellow and over 85 is green. */
data GradeAttrs; /* create discrete attribute map */
length Value $11 FillColor $15;
input raw FillColor;
Value = put(raw, GradeFmt.); /* use format to assign values */
retain ID 'GradeColors' /* name of map */
Show 'AttrMap'; /* always show all groups in legend */
datalines;
0 RED
.60 ORANGE
.70 YELLOW
.85 GREEN
;
To use the map, use the DATTRMAP= option on the PROC SGPLOT statement. Also, use the ATTRID= option on the VBAR statement. Let's add a few more students (I will use NAME instead of REGION for this example) and graph the grades:
data Class;
format Name $15. score percent6.4 range GradeFmt.;
input Name score;
range = score;
datalines;
Abbott .75
Beth .59
Carol .85
Derek .61
Ed 1.0
Felix .70
Garry .71
Harry .74
Izzy .33
Jacob .84
Ken .60
Lenora .69
Mike .99
Nancy .86
;
title "Colors According to Discrete Attribute Map";
proc sgplot data=Class dattrmap=GradeAttrs;
refline .60 .70 .85 / axis=x lineattrs=(color=blue);
hbar Name / response=score group=range attrid=GradeColors;
xaxis max=1 grid;
keylegend; /* will use the order in attribute map */
run;
Registration is now open for SAS Innovate 2025 , our biggest and most exciting global event of the year! Join us in Orlando, FL, May 6-9.
Sign up by Dec. 31 to get the 2024 rate of just $495.
Register now!
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.