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

Hey all,

 

My labels are not placing correctly. I am using a sas example to make a population pyramid style graph with proc gchart.

 

The counts should either be inside the bar, or outside, not both. Also, 20,000 on the Female side is missing and I'm not sure why. I am attaching a photo and the data set for clarity.

 

 

Here is how I have modified the code to fit my data (I have only made small changes for variable names and scale):

 

/* Set the graphics environment */                                                                                                     
goptions reset=all border cback=white htitle=12pt htext=10pt;                                                                           
                                                                                                                                                                                                                                                                              
 /* Convert the data values for one group to negative values to create the input data set, CONVERT.
	CONVERT contains the same variables as POPPYRAMIDSEXAGESTATE; however, the values of COUNT for 
	the female drivers are made negative to force a zero reference line in the bar chart. */                                                                  
data convert;                                                                                                                           
   set poppyramidsexagestate;                                                                                                                         
   if sex='FEMALE' then count=-count; 
format count comma15.; 
run;                                                                                                                                    
                                                                                                                                        
 /* Create a format for the values of COUNT.  The POSVAL. format adds a comma and suppresses the 
	sign on the values so that negative values appear as positive values. */                                                                    
proc format;                                                                                                                            
   picture posval low-high='000,009';                                                                                                   
run;                                                                                                                                    
                                                                                                                                        
 /* Create the Annotate data set, ANLABELS.  ANLABELS adds the labels to the bars.  Because data 
	values are used to place the labels, XSYS and YSYS use the absolute data coordinate system, 2.  
	A value of A for WHEN causes the labels to overlay the chart. */                                                                       
data anlabels(drop=cdcage sex );                                                                                                           
   length text $ 8;                                                                                                                     
   retain function 'label' when 'a' xsys ysys '2' hsys '3' size 2.5;                                                                    
   set convert;                                                                                                                         
   midpoint=cdcage; subgroup=sex;                                                                                                          
   text=" " || left(put(count, posval.));                                                                                              
                                                                                                                                        
   /* POSITION changes to place label outside of bar if bar is too small. */                                                            
   if count ge -1000 and sex='F' then position='<';                                                                                    
   else if sex='F' then position='>';                                                                                                   
                                                                                                                                        
   /* POSITION changes to place label outside of bar if bar is too small. */                                                            
   if count le 1000 and sex='M' then position='>';                                                                                     
   else if sex='M' then position='<';                                                                                                   
   output;                                                                                                                              
                                                                                                                                        
 run;                                                                                                                                   
                                                                                                                                        
 /* Add a title to the graph */                                                                                                         
title1 'Number of blah blah blah by Sex and Age Group, Blah 2014';                                                                                                 
                                                                                                                                        
 /* Modify the appearance of the axes. In the AXIS2 statement, the VALUE= option suppresses the third 
	tick mark so that the range for each group is zero to the maximum value. */                                                                     
axis1 label=(justify=left 'Age') style=0;                                                                                               
axis2 label=none value=(tick=3 '') minor=none major=none                                                                                
      width=3 order=(-30000 to 30000 by 5000);                                                                                         
                                                                                                                                        
 /* Create the bar chart */                                                                                                             
proc gchart data=convert;                                                                                                               
                                                                                                                                        
   /* The FORMAT statement applies the POSVAL format to the values of count. */                                                                                                       
   format count posval.;                                                                                                               
                                                                                                                                        
   /* The NOTE statement places the labels "Female" and "Male" above the population tree. */
 
   note font="Albany AMT/bold" move=(25pct,86pct) h=12pt 	'Female'                                                                        
                               move=(70pct,86pct) 			'Male';                                                                                
                                                                                                                                        
   /* In the HBAR statement, SUBGROUP=  names the variable that determines the groups, and ANNOTATE= includes the annotation defined in the ANLABELS data set. */                                                                           
   hbar cdcage / sumvar=count discrete nostat subgroup=sex 
					maxis=axis1 raxis=axis2 nolegend annotate=anlabels;                                                                       
                                                                                                                                        
run;                                                                                                                                    
quit;

 

Data set 'convert':

cdcage SEX count
1 FEMALE -863
1 MALE 1089
2 FEMALE -2219
2 MALE 3016
3 FEMALE -2240
3 MALE 3355
4 FEMALE -1425
4 MALE 3574
5 FEMALE -4472
5 MALE 11730
6 FEMALE -3740
6 MALE 11173
7 FEMALE -3255
7 MALE 8609
8 FEMALE -3962
8 MALE 8939
9 FEMALE -5341
9 MALE 7891
10 FEMALE -26304
10 MALE 15324

 


poppyramid.jpg
1 ACCEPTED SOLUTION

Accepted Solutions
ballardw
Super User

These assignments never occur:

 /* POSITION changes to place label outside of bar if bar is too small. */                                                            
   if count ge -1000 and sex='F' then position='<';                                                                                    
   else if sex='F' then position='>';                                                                                                   
                                                                                                                                        
   /* POSITION changes to place label outside of bar if bar is too small. */                                                            
   if count le 1000 and sex='M' then position='>';                                                                                     
   else if sex='M' then position='<';                                                                                                   
   output;    

because Sex has values of FEMALE and MALE not F and M.

 

 

You may need to adjust your count size for the shift as well. Your range is a bit wider than the example but you are using the same limits. Text size may also play a part in when to shift as a larger font takes up more spaces.

View solution in original post

4 REPLIES 4
Jay54
Meteorite | Level 14

If you have SAS 9.3, this is very easy with SGPLOT.  See link at bottom of article.  

I think it can be done with a single HBAR with groups.

http://blogs.sas.com/content/graphicallyspeaking/2012/07/23/butterfly-plots/

 

honk
Obsidian | Level 7

@sanjay_SAS wrote:

If you have SAS 9.3, this is very easy with SGPLOT.  See link at bottom of article.  

I think it can be done with a single HBAR with groups.

http://blogs.sas.com/content/graphicallyspeaking/2012/07/23/butterfly-plots/

 



Thank you very much! Yes, that was much easier.

 

Here is the code I used to fix it:

 

data convert_fix;
set convert;
if sex = 'FEMALE' then male = count;
if sex = 'MALE' then female = count;
agegroup = cdcage;
   format male female posval. agegroup cdcage. ;
run;

title 'Polulation by Age Group and Sex';
proc sgplot data=convert_fix;
  format male female posval. agegroup cdcage.;
  hbarparm category=agegroup response=male / dataskin=sheen
    datalabel=male datalabelattrs=(size=10);
  hbarparm category=agegroup response=female / dataskin=sheen
    datalabel=female datalabelattrs=(size=10);
  xaxis values=(-30000 to 30000 by 5000) display=(nolabel) grid;
  yaxis display=(nolabel);
run;

poppyramid2.jpg
ballardw
Super User

These assignments never occur:

 /* POSITION changes to place label outside of bar if bar is too small. */                                                            
   if count ge -1000 and sex='F' then position='<';                                                                                    
   else if sex='F' then position='>';                                                                                                   
                                                                                                                                        
   /* POSITION changes to place label outside of bar if bar is too small. */                                                            
   if count le 1000 and sex='M' then position='>';                                                                                     
   else if sex='M' then position='<';                                                                                                   
   output;    

because Sex has values of FEMALE and MALE not F and M.

 

 

You may need to adjust your count size for the shift as well. Your range is a bit wider than the example but you are using the same limits. Text size may also play a part in when to shift as a larger font takes up more spaces.

honk
Obsidian | Level 7

@ballardw wrote:

These assignments never occur:

 /* POSITION changes to place label outside of bar if bar is too small. */                                                            
   if count ge -1000 and sex='F' then position='<';                                                                                    
   else if sex='F' then position='>';                                                                                                   
                                                                                                                                        
   /* POSITION changes to place label outside of bar if bar is too small. */                                                            
   if count le 1000 and sex='M' then position='>';                                                                                     
   else if sex='M' then position='<';                                                                                                   
   output;    

because Sex has values of FEMALE and MALE not F and M.

 

 

You may need to adjust your count size for the shift as well. Your range is a bit wider than the example but you are using the same limits. Text size may also play a part in when to shift as a larger font takes up more spaces.


 

Ahhh yes! you are absolutely right, I'm not sure how I looked over that so many times.

 

This is the true fix to my problem.

 

Got it to work by changing the values of SEX and the range values.

sas-innovate-2024.png

Join us for SAS Innovate April 16-19 at the Aria in Las Vegas. Bring the team and save big with our group pricing for a limited time only.

Pre-conference courses and tutorials are filling up fast and are always a sellout. Register today to reserve your seat.

 

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
  • 4 replies
  • 2593 views
  • 4 likes
  • 3 in conversation