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

Hi! Hopefully my formating works this time! I'm creating a mirror butterfly plot and would like to change the color of the values in the bar segments to white for the segments with a black or maroon background. The remaining segments (VLIGB, red, and blue), I'd like to keep the text in black. I'd also like to change the fonts for the entire plot to Arial. The figure itself is working as intended just not these two aspects. Thank you in advance for your help!

 

Sample Data:

data WORK.DIAGNOSES;
  infile datalines dsd truncover;
  input diagnosis:$17. _2:32. _1:32. group_cat:32. group:$7.;
  label diagnosis="diagnosis" _2="_2" _1="_1" group_cat="group_cat" group="group";
datalines;
ALL 52 -52 1 Group 1
ALL 2 -2 2 Group 2
AML 10 -20 1 Group 1
AML 6 -10 2 Group 2
Breast Cancer 20 -13 2 Group 2
Breast Cancer 20 -9 1 Group 1
Breast Cancer 8 -3 3 Group 3
Colon Cancer 20 -30 1 Group 1
Lung Cancer 24 -17 1 Group 1
Stomach Cancer 7 -7 4 Group 4
Stomach Cancer 4 -4 3 Group 3
Skin Cancer 1 -1 4 Group 4
Skin Cancer 1 0 3 Group 3
Pancreatic Cancer 2 -2 3 Group 3
Prostate Cancer 2 0 5 Group 5

Sample Code:

proc format;
 picture positive
 low -< 0 = "0000"
 0 <- high = "0000";
run;

proc sgplot data = work.diagnoses noborder nowall;
styleattrs datacontrastcolors=(black) datacolors=(VLIGB red blue black maroon);
 format _1 positive.;
 format _2 positive.;
 hbar diagnosis / response = _1 group = group groupdisplay = stack barwidth=0.9 grouporder=ascending 
 attrid = myid seglabel
 seglabelfitpolicy = thin
 seglabelattrs =(size = 9 color = black weight = bold)
 name = "c1";
 hbar diagnosis / response = _2  group = group groupdisplay = stack barwidth=0.9 grouporder=ascending
 seglabel
 seglabelfitpolicy = thin
 seglabelattrs = (size = 9 color = black  weight = bold);
 xaxis /*grid gridattrs = (pattern = solid) valueattrs = (size=10 weight = bold) */
 labelattrs = (weight = bold) display=(noticks)
 label = "Patients (%)" values = (-80 to 80 by 20);
 yaxis 
display = (noline nolabel noticks) discreteorder = data 
 valueattrs = (weight=bold color=black family="Arial" size=10)label="Patients";
 keylegend "c1"/ across = 10 noborder title = '' valueattrs=(size=11) sortorder=ascending;
 inset "Insert" / position = bottomleft
 textattrs = (color = black size = 10 family="Arial"
 style = normal);
 inset "Insert" / position = bottomright
 textattrs = (color = black size = 10 weight = bold family="Arial"
 style = normal);
run;

 

1 ACCEPTED SOLUTION

Accepted Solutions
Ksharp
Super User
/*
That is really uneasy. 
I think you could use TEXT to replace SEGLABEL.
Maybe PROC TEMPLATE coould make solution easier.
*/
data WORK.DIAGNOSES;
  input diagnosis & $17. _2 _1 group_cat group $20.;
  label diagnosis="diagnosis" _2="_2" _1="_1" group_cat="group_cat" group="group";
datalines;
ALL   52 -52 1 Group 1
ALL   2 -2 2 Group 2
AML   10 -20 1 Group 1
AML   6 -10 2 Group 2
Breast Cancer   20 -13 2 Group 2
Breast Cancer   20 -9 1 Group 1
Breast Cancer   8 -3 3 Group 3
Colon Cancer   20 -30 1 Group 1
Lung Cancer   24 -17 1 Group 1
Stomach Cancer   7 -7 4 Group 4
Stomach Cancer   4 -4 3 Group 3
Skin Cancer   1 -1 4 Group 4
Skin Cancer   1 0 3 Group 3
Pancreatic Cancer   2 -2 3 Group 3
Prostate Cancer   2 0 5 Group 5
;


proc sort data=DIAGNOSES out=have;
by diagnosis group;
run;
data have2;
 set have;
 by diagnosis;
 if first.diagnosis then call missing(cum1,cum2);
 mean1=-sum(cum1,-_1/2);
 mean2=sum(cum2,_2/2);
 cum1+(-_1);
 cum2+_2;
drop cum1 cum2;
run;




proc format;
 picture positive
 low -< 0 = "0000"
 0 <- high = "0000";
run;

proc template;
define style styles.garamond;
parent=styles.listing; /* Or your favorite style */

style graphfonts from graphfonts / 
      'GraphDataFont' = ("Arial, <MTsans-serif>",7pt)               
      'GraphUnicodeFont' = ("<MTsans-serif-unicode>",9pt)                  
      'GraphValueFont' = ("Arial, <MTsans-serif>",9pt)              
      'GraphLabel2Font' = ("Arial, <MTsans-serif>",10pt)            
      'GraphLabelFont' = ("Arial, <MTsans-serif>",10pt)             
      'GraphFootnoteFont' = ("Arial, <MTsans-serif>",10pt)          
      'GraphTitleFont' = ("Arial, <MTsans-serif>",11pt,bold)        
      'GraphTitle1Font' = ("Arial, <MTsans-serif>",14pt)       
      'GraphAnnoFont' = ("Arial, <MTsans-serif>",10pt);             
end;
run;


ods listing style=garamond;
ods html  style=garamond;
proc sgplot data = have2 noborder nowall  ;
styleattrs datacontrastcolors=(black black white white white) datacolors=(VLIGB red blue black maroon);
 format _1 positive.;
 format _2 positive.;

 hbarparm category=diagnosis  response = _1/ group = group groupdisplay = stack barwidth=0.9 grouporder=ascending nooutline name="c1";
 hbarparm category=diagnosis  response = _2/ group = group groupdisplay = stack barwidth=0.9 grouporder=ascending nooutline ;

 text x=mean1 y=diagnosis text=_1 /contributeoffsets=none strip group = group textattrs=(size = 9  weight = bold);
 text x=mean2 y=diagnosis text=_2 /contributeoffsets=none strip group = group textattrs=(size = 9  weight = bold);

 xaxis labelattrs = (weight = bold) display=(noticks) label = "Patients (%)" values = (-80 to 80 by 20);
 yaxis display = (noline nolabel noticks) discreteorder = data valueattrs = (weight=bold color=black  size=10) label="Patients";

 keylegend "c1"/ across = 10 noborder title = '' valueattrs=(size=11) sortorder=ascending;

 inset "Insert" / position = bottomleft textattrs = (color = black size = 10 weight = bold style = normal);
 inset "Insert" / position = bottomright textattrs = (color = black size = 10 weight = bold style = normal);
run;

Ksharp_0-1702014321206.png

 

View solution in original post

8 REPLIES 8
Ksharp
Super User
/*
That is really uneasy. 
I think you could use TEXT to replace SEGLABEL.
Maybe PROC TEMPLATE coould make solution easier.
*/
data WORK.DIAGNOSES;
  input diagnosis & $17. _2 _1 group_cat group $20.;
  label diagnosis="diagnosis" _2="_2" _1="_1" group_cat="group_cat" group="group";
datalines;
ALL   52 -52 1 Group 1
ALL   2 -2 2 Group 2
AML   10 -20 1 Group 1
AML   6 -10 2 Group 2
Breast Cancer   20 -13 2 Group 2
Breast Cancer   20 -9 1 Group 1
Breast Cancer   8 -3 3 Group 3
Colon Cancer   20 -30 1 Group 1
Lung Cancer   24 -17 1 Group 1
Stomach Cancer   7 -7 4 Group 4
Stomach Cancer   4 -4 3 Group 3
Skin Cancer   1 -1 4 Group 4
Skin Cancer   1 0 3 Group 3
Pancreatic Cancer   2 -2 3 Group 3
Prostate Cancer   2 0 5 Group 5
;


proc sort data=DIAGNOSES out=have;
by diagnosis group;
run;
data have2;
 set have;
 by diagnosis;
 if first.diagnosis then call missing(cum1,cum2);
 mean1=-sum(cum1,-_1/2);
 mean2=sum(cum2,_2/2);
 cum1+(-_1);
 cum2+_2;
drop cum1 cum2;
run;




proc format;
 picture positive
 low -< 0 = "0000"
 0 <- high = "0000";
run;

proc template;
define style styles.garamond;
parent=styles.listing; /* Or your favorite style */

style graphfonts from graphfonts / 
      'GraphDataFont' = ("Arial, <MTsans-serif>",7pt)               
      'GraphUnicodeFont' = ("<MTsans-serif-unicode>",9pt)                  
      'GraphValueFont' = ("Arial, <MTsans-serif>",9pt)              
      'GraphLabel2Font' = ("Arial, <MTsans-serif>",10pt)            
      'GraphLabelFont' = ("Arial, <MTsans-serif>",10pt)             
      'GraphFootnoteFont' = ("Arial, <MTsans-serif>",10pt)          
      'GraphTitleFont' = ("Arial, <MTsans-serif>",11pt,bold)        
      'GraphTitle1Font' = ("Arial, <MTsans-serif>",14pt)       
      'GraphAnnoFont' = ("Arial, <MTsans-serif>",10pt);             
end;
run;


ods listing style=garamond;
ods html  style=garamond;
proc sgplot data = have2 noborder nowall  ;
styleattrs datacontrastcolors=(black black white white white) datacolors=(VLIGB red blue black maroon);
 format _1 positive.;
 format _2 positive.;

 hbarparm category=diagnosis  response = _1/ group = group groupdisplay = stack barwidth=0.9 grouporder=ascending nooutline name="c1";
 hbarparm category=diagnosis  response = _2/ group = group groupdisplay = stack barwidth=0.9 grouporder=ascending nooutline ;

 text x=mean1 y=diagnosis text=_1 /contributeoffsets=none strip group = group textattrs=(size = 9  weight = bold);
 text x=mean2 y=diagnosis text=_2 /contributeoffsets=none strip group = group textattrs=(size = 9  weight = bold);

 xaxis labelattrs = (weight = bold) display=(noticks) label = "Patients (%)" values = (-80 to 80 by 20);
 yaxis display = (noline nolabel noticks) discreteorder = data valueattrs = (weight=bold color=black  size=10) label="Patients";

 keylegend "c1"/ across = 10 noborder title = '' valueattrs=(size=11) sortorder=ascending;

 inset "Insert" / position = bottomleft textattrs = (color = black size = 10 weight = bold style = normal);
 inset "Insert" / position = bottomright textattrs = (color = black size = 10 weight = bold style = normal);
run;

Ksharp_0-1702014321206.png

 

Stilllearning
Calcite | Level 5

Thank you! This mostly worked! A few additional questions:

1. Is there a way to order the bars (can be based on the right or left side) by total bar length? Initially, I ordered my data in excel but this changed the arrangement.

2. Can you rerun the code with a more unique font? Maybe "brush". For me it seems as though the font is still not changing. I changed the "Arial" in your code to brush and the font didn't change.

3. In my dataset, several rows had zeros for the "_1" variable so I removed them from the file, leaving blank cells. One of the bars now says "dot" instead of the zero. Do you know how I can remove this? Below is a screenshot.

Capture.JPG

 

Thank you!

Ksharp
Super User
/*OK. Try this code.*/
data WORK.DIAGNOSES;
  input diagnosis & $17. _2 _1 group_cat group $20.;
  label diagnosis="diagnosis" _2="_2" _1="_1" group_cat="group_cat" group="group";
datalines;
ALL   52 -52 1 Group 1
ALL   2 -2 2 Group 2
AML   10 -20 1 Group 1
AML   6 -10 2 Group 2
Breast Cancer   20 -13 2 Group 2
Breast Cancer   20 -9 1 Group 1
Breast Cancer   8 -3 3 Group 3
Colon Cancer   20 -30 1 Group 1
Lung Cancer   24 -17 1 Group 1
Stomach Cancer   7 -7 4 Group 4
Stomach Cancer   4 -4 3 Group 3
Skin Cancer   1 -1 4 Group 4
Skin Cancer   1 0 3 Group 3
Pancreatic Cancer   2 -2 3 Group 3
Prostate Cancer   2 0 5 Group 5
;


proc sort data=DIAGNOSES out=have;
by diagnosis group;
run;
data have2;
 set have;
 by diagnosis;
 if first.diagnosis then call missing(cum1,cum2);
 mean1=-sum(cum1,-_1/2);
 mean2=sum(cum2,_2/2);
 cum1+(-_1);
 cum2+_2;

drop cum1 cum2;
run;
proc sql;
create table have3 as
select *,sum(sum(_2,-_1)) as total
 from have2
  group by diagnosis
   order by total desc,diagnosis;
quit;




proc format;
 picture positive
 low -< 0 = "0000"
 0 <- high = "0000";
run;

ods path work.tmp(update) sasuser.templat(update) sashelp.tmplmst(read);
proc template;
define style styles.garamond;
parent=styles.htmlblue; /* Or your favorite style */
style graphfonts from graphfonts / 
      'GraphDataFont' = ("Arial, <MTsans-serif>",7pt)               
      'GraphUnicodeFont' = ("<MTsans-serif-unicode>",9pt)                  
      'GraphValueFont' = ("Arial, <MTsans-serif>",9pt)              
      'GraphLabel2Font' = ("Arial, <MTsans-serif>",10pt)            
      'GraphLabelFont' = ("Arial, <MTsans-serif>",10pt)             
      'GraphFootnoteFont' = ("Arial, <MTsans-serif>",10pt)          
      'GraphTitleFont' = ("Arial, <MTsans-serif>",11pt,bold)        
      'GraphTitle1Font' = ("Arial, <MTsans-serif>",14pt)       
      'GraphAnnoFont' = ("Arial, <MTsans-serif>",10pt);             
end;
run;

ods _all_ close;
ods listing style=garamond gpath='c:\temp\';
ods graphics /outputfmt=png reset=index imagename='want';
proc sgplot data = have3 noborder nowall  ;
styleattrs datacontrastcolors=(black black white white white) datacolors=(VLIGB red blue black maroon);
 format _1 positive.;
 format _2 positive.;

 hbarparm category=diagnosis  response = _1/ group = group groupdisplay = stack barwidth=0.9 grouporder=ascending nooutline name="c1" nozerobars;
 hbarparm category=diagnosis  response = _2/ group = group groupdisplay = stack barwidth=0.9 grouporder=ascending nooutline nozerobars ;

 text x=mean1 y=diagnosis text=_1 /contributeoffsets=none strip group = group textattrs=(size = 9  weight = bold);
 text x=mean2 y=diagnosis text=_2 /contributeoffsets=none strip group = group textattrs=(size = 9  weight = bold);

 xaxis labelattrs = (weight = bold) display=(noticks) label = "Patients (%)" values = (-80 to 80 by 20);
 yaxis display = (noline nolabel noticks) discreteorder = data valueattrs = (weight=bold color=black  size=10) label="Patients";

 keylegend "c1"/ across = 10 noborder title = '' valueattrs=(size=11) sortorder=ascending;

 inset "Insert" / position = bottomleft textattrs = (color = black size = 10 weight = bold style = normal);
 inset "Insert" / position = bottomright textattrs = (color = black size = 10 weight = bold style = normal);
run;

Ksharp_0-1702022068630.png

 

 

1. Is there a way to order the bars (can be based on the right or left side) by total bar length? Initially, I ordered my data in excel but this changed the arrangement.

Ksharp_1-1702022138332.png

2. Can you rerun the code with a more unique font? Maybe "brush". For me it seems as though the font is still not changing. I changed the "Arial" in your code to brush and the font didn't change.

Ksharp_2-1702022462586.png

 

3. In my dataset, several rows had zeros for the "_1" variable so I removed them from the file, leaving blank cells. One of the bars now says "dot" instead of the zero. Do you know how I can remove this? Below is a screenshot.

 

Ksharp_3-1702022528290.png

 

Ksharp
Super User

After I used Chinese FONT (宋体) , I did get different result.

 

Ksharp_0-1702024079923.png

 

Stilllearning
Calcite | Level 5

Thank you! I was able to arrange the bars by length! For some reason the font and "nozerobars" isn't working still but I'll troubleshoot that another time. For now, I'm happy with the figure. One last question. I'd like to export as a high-resolution figure into ppt (prior this this my figure was grainy when expanded). Do you know the best way to do this? When I use "ods powerpoint file='ppt path';" and close with "ods powerpoint close; it opens the ppt file but there's no image.

Ksharp
Super User

1) First way:

Ksharp_0-1702037125888.png

2) Second way:

Using PDF destination :

ods pdf file='......' ;

proc sgplot.........

run;

ods pdf close;

 

3)Third way:

Try SVG file :

https://blogs.sas.com/content/sgf/2014/12/19/have-you-created-scalable-vector-graphics-with-sas/

https://blogs.sas.com/content/sgf/2019/02/15/scalable-svg-html5/

 

4)Fourth way:

Calling @GraphGuy  (a.k.a Robert.Allision)

Stilllearning
Calcite | Level 5

I didn't even need to go past step 1. It worked perfectly. I genuinely cannot thank you enough for all your help! I hope to get to your level of expertise one day.

Jay54
Meteorite | Level 14

FYI...BACKLIGHT option is available on TEXT plot for such use cases.  The label will be back lit with a contrasting color so the label will show up even if the bar and text colors match.  This could simplify the solution.

sas-innovate-2024.png

Available on demand!

Missed SAS Innovate Las Vegas? Watch all the action for free! View the keynotes, general sessions and 22 breakouts on demand.

 

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
  • 8 replies
  • 950 views
  • 2 likes
  • 3 in conversation