BookmarkSubscribeRSS Feed
☑ This topic is solved. Need further help from the community? Please sign in and ask a new question.
Lost_Gary
Quartz | Level 8

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

Lost_Gary_0-1708709024482.png

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.  

1 ACCEPTED SOLUTION

Accepted Solutions
Rick_SAS
SAS Super FREQ

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;

SGPlot35.png

View solution in original post

2 REPLIES 2
ballardw
Super User

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.

Rick_SAS
SAS Super FREQ

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;

SGPlot35.png

SAS Innovate 2025: Register Now

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!

How to Concatenate Values

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.

SAS Training: Just a Click Away

 Ready to level-up your skills? Choose your own adventure.

Browse our catalog!

Discussion stats
  • 2 replies
  • 566 views
  • 1 like
  • 3 in conversation