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

Morning,

 

I'm trying to use proc gchart in conjunction with the annotation facility to generate a stacked bar graph with a table annotated below. An example of my desired result is below (produced in Excel):

 

desired_result.PNG

The closest example I found was at http://support.sas.com/kb/35/774.html so this is what I modeled my code off of. I did get my data set up and was able to make the example code work and produce a graph similar to what is in the preceding link (two bars per response variable with the actual response values displayed in a grid under the bar graph). That result is below:

 

initial_result.PNG

I then began adjusting my code to create stacked bars and got my table frame and legend set up appropriately. The issue I am running into now is that the response values are scrunched to the left of my annotated table (see highlighted portion):

initial_stacked.PNG

My code is below. This is not complete (i.e. the pieces that define the raw data behind the graph are not included for brevity). I mainly need help with the /*Populate the table */ portion and curious if anyone sees anything obvious that I need to adjust to get my data annotations correctly displayed in the table. Or perhaps my gchart code is not set up correctly to do what I want. If needed I can re-post code to facility reproducibility.

data impact&spectype._forprint;
	length mid $15.;
   set impact&spectype._forprint;
	if dx ne 'Total' then do;
   response=&spectype.totreq; mid='totreq'; output; *use to display N in annotated data;
   response=totremain; mid='totremain'; output; *use to display N in annotated data;
	response=pctrequest; mid='pctrequest'; output; *use for % in y-axis of stacked bar;
	response=pctremain; mid='pctremain'; output; *use for % in y-axis of stacked bar;
	end;

keep dx response mid totremain &spectype.totreq pctrequest pctremain n;
run;
proc sort; by dx mid; run;

data impact&spectype._anno;
   set impact&spectype._forprint;
   by dx mid;
   length function color $8 text $20 style $ 20;

/* Populate the table */
   if first.dx then do;
      function='move'; xsys='2'; ysys='1';
         midpoint=mid; group=dx; y=0;
         output;
      function='cntl2txt'; output;
      function='label'; xsys='A'; ysys='3';
         x=+3; y=17.25;
         text=trim(left(put(&spectype.totreq,8.1)));
         color='black'; position='+'; when='a';
         output;
      function='move'; xsys='2'; ysys='1';
         midpoint=mid; group=dx; y=0;
         output;
      function='cntl2txt'; output;
      function='label'; xsys='A'; ysys='3';
         x=+3; y=13.75;
         text=trim(left(put(totremain,8.1)));
         color='black'; position='+'; when='a';
         output;
   end;

/* Generate the table frame */                                                                                                          
   function='move'; xsys='3'; ysys='3';                                                                                                 
      x=3; y=12;                                                                                                                         
      output;                                                                                                                           
   function='bar';  xsys='1'; ysys='3';                                                                                                 
      x=100; y=19;                                                                                                                      
      style='empty'; color='black'; line=0;                                                                                             
      output;                                                                                                                           
                                                                                                                                        
/* Generate the row headers */                                                                                                          
   function='label'; xsys='3'; ysys='3';                                                                                                
      style='marker'; text='U'; color='cxde7e6f';                                                                                       
      x=4; y=17.25; position='6';                                                                                                          
      output;                                                                                                                           
   function='label'; xsys='3'; ysys='3';                                                                                                
      style="Albany AMT"; text='Total requested'; color='black';                                                                          
      x=7; y=17.5; position='6';                                                                                                          
      output;                                                                                                                           
   function='label'; xsys='3'; ysys='3';                                                                                                
      style='marker'; text='U'; color='cx7c95ca';                                                                                       
      x=4; y=13.75; position='6';                                                                                                         
      output;                                                                                                                           
   function='label'; xsys='3'; ysys='3';                                                                                                
      style="Albany AMT"; text='Total remaining'; color='black';                                                                              
      x=7; y=14; position='6';                                                                                                           
      output;                                                                                                                           
                                                                                                                                        
/* Generate the vertical lines in the table */                                                                                          
   function='move'; xsys='1'; ysys='1';                                                                                                 
      x=0; y=0;                                                                                                                         
      output;                                                                                                                           
   function='draw'; xsys='1'; ysys='3';                                                                                                 
      x=0; y=12;                                                                                                                         
      line=1; color='black';                                                                                                            
      output;                                                                                                                           
   function='move'; xsys='1'; ysys='1';                                                                                                 
      x=100; y=0;                                                                                                                       
      output;                                                                                                                           
   function='draw'; xsys='1'; ysys='3';                                                                                                 
      x=100; y=12;                                                                                                                       
      line=1; color='black';                                                                                                            
      output;
                                                                                                                           
                                                                                                                                        
/* Generate the horizontal line in the table */                                                                                         
   function='move'; xsys='3'; ysys='3';                                                                                                 
      x=3; y=15.5;                                                                                                                      
      output;                                                                                                                           
   function='draw'; xsys='1'; ysys='3';                                                                                                 
      x=100; y=15.5;                                                                                                                    
      line=1; color='black';                                                                                                            
      output;                                                                                                                           
run;    

%mend impact;
%impact (spectype=frozen);

ods graphics;

title1 font='arial' height=10pt "Total frozen aliquots requested for R050, by final clinical diagnosis";                                                                                     
                                                                                                                                        
axis1 label=(a=90 '% Aliquots')                                                                                                 
      order=(80 to 100 by 2)                                                                                                          
      minor=none;                                                                                                                       
                                                                                                                                        
axis2 label=none                                                                                                                        
      value=none                                                                                                                        
      origin=(20pct,22pct)                                                                                                              
      offset=(4pct,4pct);                                                                                                               
                                                                                                                                        
axis3 label=none;                                                                                                                       
                                                                                                                                        
footnote1 h=.5 '  ';                                                                                                                    

pattern1 value=solid color=cx7c95ca;                                                                                                    
pattern2 value=solid color=cxde7e6f;                                                                                                    

ods pdf file="X:\XXX\COMMON\Requests\test.pdf";

proc gchart data=impactfrozen_forprint (where=(mid in ('pctremain','pctrequest')));                                                                                                                   
   vbar dx / sumvar=response subgroup=mid group=dx g100 nozero
              coutline=black                                                                                         
              space=0 gspace=5 width=4                                                                                                  
              cframe=white autoref clipref                                                                                             
              raxis=axis1 maxis=axis2 gaxis=axis3 nolegend
              annotate=impactfrozen_anno; 

run; quit;  
ods pdf close;

 

1 ACCEPTED SOLUTION

Accepted Solutions
GraphGuy
Meteorite | Level 14

Here's one way to do it with gchart and annotate:

 

%let name=bar_table;
filename odsout '.';

goptions device=png;
goptions border;
 
ODS LISTING CLOSE;
ODS HTML path=odsout body="&name..htm" style=htmlblue;

goptions gunit=pct htitle=6 ftitle="albany amt/bold" htext=4.25 ftext="albany amt";
gopitons ctext=gray33;

data dx;
input nmid $ pctmid $ dx $ nresponse pctresponse;
datalines;
totreq pctreq COPD 18 0.20
totrem pctrem COPD 8800 99.80
totreq pctreq Control 5 0.52
totrem pctrem Control 949 99.48
totreq pctreq ILD 0 0
totrem pctrem ILD 8124 100
totreq pctreq Other 200 12.93
totrem pctrem Other 1546 87.07
;
run;

data dx; set dx;
format pctresponse percentn7.0;
pctresponse=pctresponse/100;
run;

data anno_values; set dx;
xsys='2'; ysys='3'; hsys='3'; when='a';
function='label'; position='5'; 
xc=dx; 
if nmid='totreq' then do;
 y=15; 
 text=trim(left(nresponse));
 output;
 end;
if nmid='totrem' then do;
 y=7; 
 text=trim(left(nresponse));
 output;
 end;
run;

data anno_lines;
length function $8 color $8 style $35;
when='b';
color='cx989ea1';
/* vertical lines */
xsys='1'; x=0; ysys='1'; y=0; function='move'; output;
xsys='1'; x=0; ysys='3'; y=2; function='draw'; output;
xsys='1'; x=25; ysys='1'; y=0; function='move'; output;
xsys='1'; x=25; ysys='3'; y=2; function='draw'; output;
xsys='1'; x=50; ysys='1'; y=0; function='move'; output;
xsys='1'; x=50; ysys='3'; y=2; function='draw'; output;
xsys='1'; x=75; ysys='1'; y=0; function='move'; output;
xsys='1'; x=75; ysys='3'; y=2; function='draw'; output;
xsys='1'; x=100; ysys='1'; y=0; function='move'; output;
xsys='1'; x=100; ysys='3'; y=2; function='draw'; output;
xsys='3'; x=3; ysys='3'; y=18; function='move'; output;
xsys='3'; x=3; ysys='3'; y=2; function='draw'; output;

/* horizontal lines */
xsys='3'; x=3; ysys='3'; y=18; function='move'; output;
xsys='1'; x=100; ysys='3'; y=18; function='draw'; output;
xsys='3'; x=3; ysys='3'; y=10; function='move'; output;
xsys='1'; x=100; ysys='3'; y=10; function='draw'; output;
xsys='3'; x=3; ysys='3'; y=2; function='move'; output;
xsys='1'; x=100; ysys='3'; y=2; function='draw'; output;

/* white-out some of the lines behind the 'Frozen' label */
xsys='1'; x=10; ysys='3'; y=18.1; function='move'; output;
xsys='1'; x=90; ysys='3'; y=27; function='box'; style='solid'; color='white'; output;

/* labels to left of table */
function='label'; position='6'; color=''; style='';
xsys='3'; x=10; ysys='3'; y=15; text='Total requested'; output;
xsys='3'; x=10; ysys='3'; y=7; text='Total remaining'; output;
style='marker'; text='U';
xsys='3'; x=5; ysys='3'; y=15-.5; color="cxc6514a"; output;
xsys='3'; x=5; ysys='3'; y=7-.5; color="cx4a82bd"; output;


run;

data anno_all; set anno_lines anno_values;
run;


pattern1 v=s c=cx4a82bd;
pattern2 v=s c=cxc6514a;

axis1 label=none order=(0 to 1 by 1) minor=none offset=(0,0);

axis2 label=('Frozen') order=('ILD' 'COPD' 'Control' 'Other');

title1 a=90 h=20 ' '; /* blank space to the left of the bar chart */
footnote1 height=15pct ' '; /* blank space for the annotated table */

proc gchart data=dx anno=anno_all;
vbar dx / type=sum sumvar=pctresponse
 subgroup=nmid nolegend
 raxis=axis1 maxis=axis2
 coutline=gray77;
run;

quit;
ODS HTML CLOSE;
ODS LISTING;

gchart.png

View solution in original post

3 REPLIES 3
RW9
Diamond | Level 26 RW9
Diamond | Level 26

Move to the modern graphing system - sgplot/GTL.  Examples:

https://blogs.sas.com/content/?s=stacked

 

And you will find everything you ever wanted to know about graphs at:

https://blogs.sas.com/content/graphicallyspeaking/

lbarwick
Quartz | Level 8

Thanks. I think I found a solution. Here is some sample code I developed that is getting me to where I need to be (just need to add labels):

 


data dx;
input nmid $ pctmid $ dx $ nresponse pctresponse;
datalines;
totreq pctreq COPD 18 0.20
totrem pctrem COPD 8800 99.80
totreq pctreq Control 5 0.52
totrem pctrem Control 949 99.48
totreq pctreq ILD 0 0
totrem pctrem ILD 8124 100
totreq pctreq Other 200 12.93
totrem pctrem Other 1546 87.07
;
run; proc sort; by dx descending pctresponse; run;


ods graphics;                                                                                               

ods pdf file="X:\test1.pdf";
proc sgplot data=dx;
  title 'Frozen specimens requested';
  vbarparm category=dx response=pctresponse / group=pctmid dataskin=gloss;
  xaxistable nresponse / class=nmid label labelpos=left location=inside;
  xaxis display=(nolabel);
  keylegend / location=inside position=topright;
  yaxis offsetmax=0.1;
  run;
ods pdf close;
GraphGuy
Meteorite | Level 14

Here's one way to do it with gchart and annotate:

 

%let name=bar_table;
filename odsout '.';

goptions device=png;
goptions border;
 
ODS LISTING CLOSE;
ODS HTML path=odsout body="&name..htm" style=htmlblue;

goptions gunit=pct htitle=6 ftitle="albany amt/bold" htext=4.25 ftext="albany amt";
gopitons ctext=gray33;

data dx;
input nmid $ pctmid $ dx $ nresponse pctresponse;
datalines;
totreq pctreq COPD 18 0.20
totrem pctrem COPD 8800 99.80
totreq pctreq Control 5 0.52
totrem pctrem Control 949 99.48
totreq pctreq ILD 0 0
totrem pctrem ILD 8124 100
totreq pctreq Other 200 12.93
totrem pctrem Other 1546 87.07
;
run;

data dx; set dx;
format pctresponse percentn7.0;
pctresponse=pctresponse/100;
run;

data anno_values; set dx;
xsys='2'; ysys='3'; hsys='3'; when='a';
function='label'; position='5'; 
xc=dx; 
if nmid='totreq' then do;
 y=15; 
 text=trim(left(nresponse));
 output;
 end;
if nmid='totrem' then do;
 y=7; 
 text=trim(left(nresponse));
 output;
 end;
run;

data anno_lines;
length function $8 color $8 style $35;
when='b';
color='cx989ea1';
/* vertical lines */
xsys='1'; x=0; ysys='1'; y=0; function='move'; output;
xsys='1'; x=0; ysys='3'; y=2; function='draw'; output;
xsys='1'; x=25; ysys='1'; y=0; function='move'; output;
xsys='1'; x=25; ysys='3'; y=2; function='draw'; output;
xsys='1'; x=50; ysys='1'; y=0; function='move'; output;
xsys='1'; x=50; ysys='3'; y=2; function='draw'; output;
xsys='1'; x=75; ysys='1'; y=0; function='move'; output;
xsys='1'; x=75; ysys='3'; y=2; function='draw'; output;
xsys='1'; x=100; ysys='1'; y=0; function='move'; output;
xsys='1'; x=100; ysys='3'; y=2; function='draw'; output;
xsys='3'; x=3; ysys='3'; y=18; function='move'; output;
xsys='3'; x=3; ysys='3'; y=2; function='draw'; output;

/* horizontal lines */
xsys='3'; x=3; ysys='3'; y=18; function='move'; output;
xsys='1'; x=100; ysys='3'; y=18; function='draw'; output;
xsys='3'; x=3; ysys='3'; y=10; function='move'; output;
xsys='1'; x=100; ysys='3'; y=10; function='draw'; output;
xsys='3'; x=3; ysys='3'; y=2; function='move'; output;
xsys='1'; x=100; ysys='3'; y=2; function='draw'; output;

/* white-out some of the lines behind the 'Frozen' label */
xsys='1'; x=10; ysys='3'; y=18.1; function='move'; output;
xsys='1'; x=90; ysys='3'; y=27; function='box'; style='solid'; color='white'; output;

/* labels to left of table */
function='label'; position='6'; color=''; style='';
xsys='3'; x=10; ysys='3'; y=15; text='Total requested'; output;
xsys='3'; x=10; ysys='3'; y=7; text='Total remaining'; output;
style='marker'; text='U';
xsys='3'; x=5; ysys='3'; y=15-.5; color="cxc6514a"; output;
xsys='3'; x=5; ysys='3'; y=7-.5; color="cx4a82bd"; output;


run;

data anno_all; set anno_lines anno_values;
run;


pattern1 v=s c=cx4a82bd;
pattern2 v=s c=cxc6514a;

axis1 label=none order=(0 to 1 by 1) minor=none offset=(0,0);

axis2 label=('Frozen') order=('ILD' 'COPD' 'Control' 'Other');

title1 a=90 h=20 ' '; /* blank space to the left of the bar chart */
footnote1 height=15pct ' '; /* blank space for the annotated table */

proc gchart data=dx anno=anno_all;
vbar dx / type=sum sumvar=pctresponse
 subgroup=nmid nolegend
 raxis=axis1 maxis=axis2
 coutline=gray77;
run;

quit;
ODS HTML CLOSE;
ODS LISTING;

gchart.png

hackathon24-white-horiz.png

2025 SAS Hackathon: There is still time!

Good news: We've extended SAS Hackathon registration until Sept. 12, so you still have time to be part of our biggest event yet – our five-year anniversary!

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
  • 3 replies
  • 2136 views
  • 1 like
  • 3 in conversation