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

How to and choose to add the color of my choice to the bar charts created using the sg plot procedure. Also, how to display the count figures and the same in percentages on top of each bars(outside on top of the bar) as a representation. For example, (2378, 44%) is a kind of representation that I am used to creating in excel on top of each of the bar charts. Can the same be done using sas graph ods graphics.

 

The code i am using creates simple bar charts that needs to be tweaked. Please advice

 

proc sgplot data=sample;
 vbar city /response=profit datalabel;
run;

 

 

1 ACCEPTED SOLUTION

Accepted Solutions
GraphGuy
Meteorite | Level 14

Here's one way to create the bar chart you attached, using SAS/Graph gchart ...

 

data my_data;
input customer_count salary_range $ 6-80;
bar_order+1;
datalines;
1264 0-5000
8077 5,001-10,000
3607 10,001-20,000
1431 20,001-35,000
354 35,001-50,000
278 50,001 and\above
340 Salary not\declared
;
run;

 

proc sql;
select sum(customer_count) into :total from my_data;
quit; run;

 

data my_data; set my_data;
percent_customers=customer_count/&total;
run;

 

data anno_labels; set my_data;
xsys='2'; ysys='2'; hsys='3'; when='a';
x=bar_order; y=percent_customers;
function='label'; position='2';
text=trim(left(put(customer_count,comma8.0)))||', '||trim(left(put(percent_customers,percentn7.1)));
run;

 

/* Create a user-defined-format to print the numeric bar_order as the salary_range */
proc sql noprint;
create table foo as select unique bar_order as start, salary_range as label from my_data;
quit; run;
data control; set foo;
fmtname = 'barfmt';
type = 'N';
end = START;
run;
proc format lib=work cntlin=control;
run;

 

axis1 label=none style=0 major=none minor=none;
axis2 label=none split='\';

pattern1 v=s c=gray88;

goptions htext=2.0 pct;

 

proc gchart data=my_data anno=anno_labels;
format percent_customers percentn6.0;
format bar_order barfmt.;
vbar bar_order / discrete type=sum sumvar=percent_customers
raxis=axis1 maxis=axis2 noframe coutline=gray44;
run;

 

custom_bar.png

 


custom_bar.png

View solution in original post

15 REPLIES 15
Reeza
Super User
Create a variable that contains what you want in the datalabel and then refer to that in your code.

datalabel=label_variable

Setting a color choice is more difficult than it seems.
Here's an example from the SAS docs. Some of these options may only be valid in SAS 9.4.

http://support.sas.com/documentation/cdl/en/grstatproc/67909/HTML/default/viewer.htm#p18q268a3zxcl3n...
pearsoninst
Pyrite | Level 9
Hi ,

Here you go, However i did not get how to show both numer and % .Hope this some what helps

proc sgplot data=newdata ;
 vbar city /response = profit  datalabel BARWIDTH = 0.2 
 fillattrs=(COLOR=RED)  STAT=percent;
run;
Jay54
Meteorite | Level 14

Setting bar color for a non-grouped bar chart is very easy as shown by "Pearsoninst".  Use DATALABEL option to either show the response value, or DATALABEL=column to display the value from another column (say Label).  Note, if there are more than one observations per category, I believe the first value is shown.  You can generate a Label colum that includes the information you want to show.  If the Label column type is character, the label can be split on white space.

 

If your graph has a GROUP role, the groups are colored by their order in the data using GraphData1 - 12 colors defined in the style. You can use the STYLEATTS statement to change the list of colors.

Allaluiah
Quartz | Level 8

@Jay54 Thank you, I have understood how to fill the color of my choice. However, my need is also to get the frequency statistics and percentages in the same graph report. 

What I mean is like inside= statistic and outside=statistics in the vbar. I'd prefer to represent frequency outside on top on the bars and the percentages inside the bars. 

For example, let's say i have a data set 

city                 custumer_Count

LA                    35

New york         49

Dallas               29

 

I want  the customer_count figues in the dataset to be represented on top of the graphs(outside) and it's percentages inside the graph. Can yor or anybody reading this thread help?  

DanH_sas
SAS Super FREQ

What version of SAS are you using?

Allaluiah
Quartz | Level 8

HI @DanH_sas and @Jay54 I am using SAS enterprise guide 5.1 and I don't think i have 9.4. I believe it is 9.3 or 9.2, honestly not sure. 

Jay54
Meteorite | Level 14

With SAS 9.4 you can use SEGLABEL to draw values in the bar and DATALABEL to draw values above the bar.  Or you can use AXISTABLE.  Compute the percent values as a new column.

 

proc sgplot data=customer2 nowall noborder;
  vbarparm category=city response=percent / datalabel=count seglabel;
  yaxis display=none grid;
run;


Customer.png
Jay54
Meteorite | Level 14

With VBARPARM (without stacked groups), you can still use the SCATTER plot with MARKERCHAR to overlay the segment values in the middle of the bar.

Allaluiah
Quartz | Level 8

@Jay54 and @DanH_sasThank you for your responses. I'm afraid  the VBARPARM doesn't seem to be functional in my SAS enterprise guide 5.1. I researched quite a bit on SAS online documentation, and I found proc ghcart is the only one that comes close to my requirement with inside=  and outside=statistics to display the frequency and percentages in the vertical bars.

 

Although, i am close i am stuck in reshaping the bar sizes coz when bar is too small, it misses to display the percentages inside. Also, I am unable to find out ways to remove the default frequency label on the left side of the y axis. The names of the category variable is veritcally displayed while it should actually be diagonal.

 

Any further suggestions plz

Jay54
Meteorite | Level 14

Please attach a picture of what you want and sample data.  

Allaluiah
Quartz | Level 8

Thank you @Jay54 I appreciate your response. I have attached a pic of the excel graph that I would like. 

 

The sample data is as follows:(Salary_range is a character variable and Customer count is numeric and there are no duplicates whatsoever and the attached graph is merely a representation in numbers as percentages and as simple as it looks in excel and I have been struggling to achieve the same in SAS. Please help if you can. Thanks once again

Salary_range Customer_count
0-5000 1264
5001-10000 8077
10001-20000 3607
20001-35000 1431
35001-50000 354
50001 and above 278
Salary not declared 340

samplechart_fromexcel.jpg
GraphGuy
Meteorite | Level 14

Here's one way to create the bar chart you attached, using SAS/Graph gchart ...

 

data my_data;
input customer_count salary_range $ 6-80;
bar_order+1;
datalines;
1264 0-5000
8077 5,001-10,000
3607 10,001-20,000
1431 20,001-35,000
354 35,001-50,000
278 50,001 and\above
340 Salary not\declared
;
run;

 

proc sql;
select sum(customer_count) into :total from my_data;
quit; run;

 

data my_data; set my_data;
percent_customers=customer_count/&total;
run;

 

data anno_labels; set my_data;
xsys='2'; ysys='2'; hsys='3'; when='a';
x=bar_order; y=percent_customers;
function='label'; position='2';
text=trim(left(put(customer_count,comma8.0)))||', '||trim(left(put(percent_customers,percentn7.1)));
run;

 

/* Create a user-defined-format to print the numeric bar_order as the salary_range */
proc sql noprint;
create table foo as select unique bar_order as start, salary_range as label from my_data;
quit; run;
data control; set foo;
fmtname = 'barfmt';
type = 'N';
end = START;
run;
proc format lib=work cntlin=control;
run;

 

axis1 label=none style=0 major=none minor=none;
axis2 label=none split='\';

pattern1 v=s c=gray88;

goptions htext=2.0 pct;

 

proc gchart data=my_data anno=anno_labels;
format percent_customers percentn6.0;
format bar_order barfmt.;
vbar bar_order / discrete type=sum sumvar=percent_customers
raxis=axis1 maxis=axis2 noframe coutline=gray44;
run;

 

custom_bar.png

 


custom_bar.png
Jay54
Meteorite | Level 14

And if you are a SAS 9.4 SGPLOT user, here is the code you need.  I used Robert code with some modifications.  Thanks, Robert.

Note the "space" after the "-" in the salary_range values used as the split character.

 

data my_data;
input customer_count salary_range $ 6-80;
bar_order+1;
datalines;
1264 0-5000
8077 5,001- 10,000
3607 10,001- 20,000
1431 20,001- 35,000
354 35,001- 50,000
278 50,001 and\above
340 Salary not\declared
;
run;

proc sql;
select sum(customer_count) into :total from my_data;
quit; run;

 

data my_data; set my_data;
  format percent_customers percent5.0;
  percent_customers=customer_count/&total;
  label=put(customer_count, 4.0) || ', ' || put(percent_customers, percent5.0);
run;

 

proc sgplot data=my_data nowall noborder;
  vbarparm category=salary_range response=percent_customers / datalabelattrs=(size=8)
  barwidth=0.6 datalabel=label fillattrs=(color=gray) nooutline;
  xaxis display=(nolabel noline noticks);
  yaxis display=(nolabel noline noticks) grid;
run;

 

BarPercent.png

Allaluiah
Quartz | Level 8

@GraphGuy you are a star!, how did you gain this level of expertise and how long did it take? simple awesome!!!!!!!!!!!!!!!!!!!! Thank you so much

sas-innovate-2024.png

Don't miss out on SAS Innovate - Register now for the FREE Livestream!

Can't make it to Vegas? No problem! Watch our general sessions LIVE or on-demand starting April 17th. Hear from SAS execs, best-selling author Adam Grant, Hot Ones host Sean Evans, top tech journalist Kara Swisher, AI expert Cassie Kozyrkov, and the mind-blowing dance crew iLuminate! Plus, get access to over 20 breakout sessions.

 

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.

Click image to register for webinarClick image to register for webinar

Classroom Training Available!

Select SAS Training centers are offering in-person courses. View upcoming courses for:

View all other training opportunities.

Discussion stats
  • 15 replies
  • 2735 views
  • 3 likes
  • 6 in conversation