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

Hi @Ksharp 

 

Thank you for the contribution. I see you already given multiple different ( Permutation and Combination) of questions asked on this topic. 

I was running the code using  PROC SGPLOT Inspired  from the @Jay54  (https://blogs.sas.com/content/graphicallyspeaking/2017/10/30/fill-patterns/)

This request looks similar to what you explained with proc template but using PROCSGPLOT. like in your output you have three box for each region.  but the colors are different for each car type but patttern is same for the Region. Can we do the other way around, each Region will have one different color, and each cartype will have the  same pattern across  the three different regions.

 

In my Example, I am expecting below,  but its not comming as expected. 

Treatment A =  Blue color, Age group: Young  = L1 Pattern, datasymbol = Circlefilled ; Old  = X1 Pattern Datasymbol = square filled;

Treatment B =  salmon color, Age group: Young  = L1 Pattern, datasymbol = Circlefilled ; Old  = X1 Pattern Datasymbol = square filled;

Treatment C =  Green color, Age group: Young  = L1 Pattern, datasymbol = Circlefilled ;   Old  = X1 Pattern, Datasymbol = square filled;

Legends will be as per the above assignment/ counts displayed inner axis. Can you please help. thank you very much

/* Create sample dataset */
data treatment_data;
    input Treatment $ AgeGroup $ Value @@;
    /* Create a combined group variable for styling */
    length GroupVar $20;
    if Treatment='A' and AgeGroup='Young' then GroupVar='A_Young';
    else if Treatment='A' and AgeGroup='Old' then GroupVar='A_Old';
    else if Treatment='B' and AgeGroup='Young' then GroupVar='B_Young';
    else if Treatment='B' and AgeGroup='Old' then GroupVar='B_Old';
    else if Treatment='C' and AgeGroup='Young' then GroupVar='C_Young';
    else if Treatment='C' and AgeGroup='Old' then GroupVar='C_Old';
    datalines;
A Young 25 A Young 28 A Young 30 A Young 22 A Young 26
A Old   32 A Old   35 A Old   38 A Old   30 A Old   33
B Young 18 B Young 20 B Young 22 B Young 19 B Young 21
B Old   28 B Old   30 B Old   32 B Old   27 B Old   29
C Young 30 C Young 32 C Young 34 C Young 31 C Young 33
C Old   40 C Old   42 C Old   45 C Old   38 C Old   41
;
run;

/* Create box plot with custom styling */
ods graphics on / attrpriority=color;
ods rtf file="xx\text_color_patrn.rtf" style=mypatterns;

proc sgplot data=treatment_data;
    title "Box Plot with Custom Treatment Colors and Age Patterns";
 styleattrs datacolors=(lightblue  salmon lightblue  salmon lightgreen lightgreen )
               datafillpatterns=(L1  X1)
			   DATASYMBOLS=( circlefilled squarefilled  )
				datacontrastcolors=(blue red  green); /* Young=L1, Old=X1 for all treatments */
   
    vbox Value / category=Treatment 
                 group=AgeGroup 
                 groupdisplay=cluster 
                 nooutliers 
                 fillpattern
/*                 fillattrs=(transparency=0.3)*/
                 grouporder=data;
    
    /* Assign specific colors and patterns */
    
    xaxis label="Treatment";
    yaxis label="Measurement Value" grid;
    
    /* Custom legend */
    keylegend / title="Age Group" 
               position=topright 
               across=1;
run;
ods rtf close;

 

Ksharp
Super User

You want this ?

 

/* Create sample dataset */
data treatment_data;
    input Treatment $ AgeGroup $ Value @@;
    /* Create a combined group variable for styling */
    length AgeGroup GroupVar $20;
    if Treatment='A' and AgeGroup='Young' then GroupVar='A_Young';
    else if Treatment='A' and AgeGroup='Old' then GroupVar='A_Old';
    else if Treatment='B' and AgeGroup='Young' then GroupVar='B_Young';
    else if Treatment='B' and AgeGroup='Old' then GroupVar='B_Old';
    else if Treatment='C' and AgeGroup='Young' then GroupVar='C_Young';
    else if Treatment='C' and AgeGroup='Old' then GroupVar='C_Old';
    datalines;
A Young 25 A Young 28 A Young 30 A Young 22 A Young 26
A Old   32 A Old   35 A Old   38 A Old   30 A Old   33
B Young 18 B Young 20 B Young 22 B Young 19 B Young 21
B Old   28 B Old   30 B Old   32 B Old   27 B Old   29
C Young 30 C Young 32 C Young 34 C Young 31 C Young 33
C Old   40 C Old   42 C Old   45 C Old   38 C Old   41
;
run;


/* Create box plot with custom styling */
ods graphics on / attrpriority=none;

proc sgplot data=treatment_data;


    title "Box Plot with Custom Treatment Colors and Age Patterns";
 styleattrs datacolors=(blue blue red red  green green )
               datafillpatterns=(L1  X1)
			   DATASYMBOLS=( circlefilled squarefilled  )
				datacontrastcolors=(black); /* Young=L1, Old=X1 for all treatments */
   

 vbox Value / category=Treatment 
                 group=AgeGroup 
                 groupdisplay=cluster 
                 nooutliers fillpattern fillattrs=(color=white)
                 grouporder=data name='x';


  vbox Value / category=Treatment 
                 group=GroupVar 
                 groupdisplay=cluster 
                 nooutliers 
                 fillpattern
/*                 fillattrs=(transparency=0.3)*/
                 grouporder=data;
    
    
    xaxis label="Treatment";
    yaxis label="Measurement Value" grid;
    
    /* Custom legend */
    keylegend 'x'/ title="Age Group" 
               position=topright 
               across=1;
run;

Ksharp_0-1746971424848.png

 

Jay_2023
Calcite | Level 5

Yes. You applied 2 'Vbox ' statements, one for color and one for pattern? If you don't mind 2 more questions.

1. can we display the counts on x axis  ( inner axis table) for those boxes like you did in another graph, I tried merging with counts but it messing the graphs, So I must be doing wrong.

2.  For legends, can we apply the color that reflects in the data? Do we need to create another variable to display 6 legends ( 3 treat X 2 pattern = 6 legends)? I see your response in this topic, We still have to depend on "Style.Patterns"? If Yes, Please ignore this request. As it looks complicated for me to understand. 

 

Thank you so much for Your time. I really appreciate your time.

Ksharp
Super User

For your first question, yes, you can include COUNT with XAXISTABLE.

/* Create sample dataset */
data treatment_data;
    input Treatment $ AgeGroup $ Value @@;
    /* Create a combined group variable for styling */
    length AgeGroup GroupVar $20;
    if Treatment='A' and AgeGroup='Young' then GroupVar='A_Young';
    else if Treatment='A' and AgeGroup='Old' then GroupVar='A_Old';
    else if Treatment='B' and AgeGroup='Young' then GroupVar='B_Young';
    else if Treatment='B' and AgeGroup='Old' then GroupVar='B_Old';
    else if Treatment='C' and AgeGroup='Young' then GroupVar='C_Young';
    else if Treatment='C' and AgeGroup='Old' then GroupVar='C_Old';
    datalines;
A Young 25 A Young 28 A Young 30 A Young 22 A Young 26
A Old   32 A Old   35 A Old   38 A Old   30 A Old   33
B Young 18 B Young 20 B Young 22 B Young 19 B Young 21
B Old   28 B Old   30 B Old   32 B Old   27 B Old   29
C Young 30 C Young 32 C Young 34 C Young 31 C Young 33
C Old   40 C Old   42 C Old   45 C Old   38 C Old   41
;
run;

proc sql;
create table treatment_data2 as
select *,count(*) as n from treatment_data group by Treatment,GroupVar;
quit;
data treatment_data2;
 set treatment_data2;
 by Treatment GroupVar;
 if not first.GroupVar then call missing(n);
run;


/* Create box plot with custom styling */
ods graphics on / attrpriority=none;

proc sgplot data=treatment_data2;


    title "Box Plot with Custom Treatment Colors and Age Patterns";
 styleattrs datacolors=(blue blue red red  green green )
               datafillpatterns=(L1  X1)
			   DATASYMBOLS=( circlefilled squarefilled  )
				datacontrastcolors=(black); /* Young=L1, Old=X1 for all treatments */
   

 vbox Value / category=Treatment 
                 group=AgeGroup 
                 groupdisplay=cluster 
                 nooutliers fillpattern fillattrs=(color=white)
                 grouporder=data name='x';


  vbox Value / category=Treatment 
                 group=GroupVar 
                 groupdisplay=cluster 
                 nooutliers 
                 fillpattern
/*                 fillattrs=(transparency=0.3)*/
                 grouporder=data;
    
    
xaxistable n/x=Treatment class=GroupVar classdisplay=cluster location=inside ;

    xaxis label="Treatment";
    yaxis label="Measurement Value" grid;
    
    /* Custom legend */
    keylegend 'x'/ title="Age Group" 
               position=topright 
               across=1;
run;

Ksharp_0-1747013044042.png

 

 

For your second question. Can you post the desired output ? I don't understand "  For legends, can we apply the color that reflects in the data?".

Or you maybe display all the "6 legends ( 3 treat X 2 pattern = 6 legends)".

/* Create box plot with custom styling */
ods graphics on / attrpriority=none;

proc sgplot data=treatment_data2;


    title "Box Plot with Custom Treatment Colors and Age Patterns";
 styleattrs datacolors=(blue blue red red  green green )
               datafillpatterns=(L1  X1)
			   DATASYMBOLS=( circlefilled squarefilled  )
				datacontrastcolors=(black); /* Young=L1, Old=X1 for all treatments */
   


  vbox Value / category=Treatment 
                 group=GroupVar 
                 groupdisplay=cluster 
                 nooutliers 
                 fillpattern
/*                 fillattrs=(transparency=0.3)*/
                 grouporder=data  name='x';
    
    
xaxistable n/x=Treatment class=GroupVar classdisplay=cluster location=inside ;

    xaxis label="Treatment";
    yaxis label="Measurement Value" grid;
    
    /* Custom legend */
    keylegend 'x'/ title="Age Group" 
               position=topright 
               across=1;
run;

Ksharp_1-1747013253692.png

 

 

 

 

Or you could plot it as :

/* Create box plot with custom styling */
ods graphics on / attrpriority=none;

proc sgplot data=treatment_data2;


    title "Box Plot with Custom Treatment Colors and Age Patterns";
 styleattrs 
               datafillpatterns=(L1  X1)
			   DATASYMBOLS=( circlefilled squarefilled  )
				datacontrastcolors=(black); /* Young=L1, Old=X1 for all treatments */
   


 vbox Value / category=Treatment 
                 group=AgeGroup 
                 groupdisplay=cluster 
                 nooutliers fillpattern fillattrs=(color=white)
                 grouporder=data name='x';
    
    
xaxistable n/x=Treatment class=GroupVar classdisplay=cluster location=inside ;

    xaxis label="Treatment" colorbands=even;
    yaxis label="Measurement Value" grid;
    
    /* Custom legend */
    keylegend 'x'/ title="Age Group" 
               position=topright 
               across=1;
run;

Ksharp_0-1747030203749.png

 

 

Jay_2023
Calcite | Level 5

Hi @Ksharp. I don't think I need to post the data, as your second output answered my expectations. Thank you so much. Really appreciate it. And you are awesome. I have one more question. How to control the groups on the x-axis so that they always come in the order I want. Since here  A, B, C is alphabetical order.  I want to display them in B, A, C order, so giving numeric numbering will help me?

Ksharp
Super User

You could change the order of X axis value by padding some blanks before it. Here is an example:

 

/* Create sample dataset */
data treatment_data;
    input Treatment $ AgeGroup $ Value @@;
    /* Create a combined group variable for styling */
    length AgeGroup GroupVar $ 20;
    if Treatment='A' and AgeGroup='Young' then GroupVar='A_Young';
    else if Treatment='A' and AgeGroup='Old' then GroupVar='A_Old';
    else if Treatment='B' and AgeGroup='Young' then GroupVar='B_Young';
    else if Treatment='B' and AgeGroup='Old' then GroupVar='B_Old';
    else if Treatment='C' and AgeGroup='Young' then GroupVar='C_Young';
    else if Treatment='C' and AgeGroup='Old' then GroupVar='C_Old';
    datalines;
A Young 25 A Young 28 A Young 30 A Young 22 A Young 26
A Old   32 A Old   35 A Old   38 A Old   30 A Old   33
B Young 18 B Young 20 B Young 22 B Young 19 B Young 21
B Old   28 B Old   30 B Old   32 B Old   27 B Old   29
C Young 30 C Young 32 C Young 34 C Young 31 C Young 33
C Old   40 C Old   42 C Old   45 C Old   38 C Old   41
;
run;

proc sql;
create table treatment_data2 as
select *,count(*) as n from treatment_data group by Treatment,GroupVar;
quit;
data treatment_data2;
length Treatment $ 20;
 set treatment_data2;
 by Treatment GroupVar;
 if not first.GroupVar then call missing(n);

 if Treatment='B' then Treatment='  B';
   else  if Treatment='C' then Treatment=' C';

run;


/* Create box plot with custom styling */
ods graphics on / attrpriority=none;

proc sgplot data=treatment_data2;


    title "Box Plot with Custom Treatment Colors and Age Patterns";
 styleattrs 
               datafillpatterns=(L1  X1)
			   DATASYMBOLS=( circlefilled squarefilled  )
				datacontrastcolors=(black); /* Young=L1, Old=X1 for all treatments */
   


 vbox Value / category=Treatment 
                 group=AgeGroup 
                 groupdisplay=cluster 
                 nooutliers fillpattern fillattrs=(color=white)
                  name='x';
    
    
xaxistable n/x=Treatment class=GroupVar classdisplay=cluster location=inside ;

    xaxis label="Treatment" colorbands=even;
    yaxis label="Measurement Value" grid;
    
    /* Custom legend */
    keylegend 'x'/ title="Age Group" 
               position=topright 
               across=1;
run;

Ksharp_0-1747098105251.png

 

Jay_2023
Calcite | Level 5

Hi @Ksharp again. Sorry for bothering. What are the options I can play with if the x-axis table count numbers do not align with the boxes, like in the image with 'Red' color numbers. I tried with 'offsetmin'  and clusterwidth in the 'xaxis' and ' vbox' statements.  Is any other options available? if you can direct me, I can play with the graph. Thank you.

Jay_2023_0-1747263976726.png

 

Ksharp
Super User

Unfortunately, there is not such option for XAXISTABLE statment.

But you can mimic it by SCATTER statement, if you really need it.

 

/* Create sample dataset */
data treatment_data;
    input Treatment $ AgeGroup $ Value @@;
    /* Create a combined group variable for styling */
    length AgeGroup GroupVar $ 20;
    if Treatment='A' and AgeGroup='Young' then GroupVar='A_Young';
    else if Treatment='A' and AgeGroup='Old' then GroupVar='A_Old';
    else if Treatment='B' and AgeGroup='Young' then GroupVar='B_Young';
    else if Treatment='B' and AgeGroup='Old' then GroupVar='B_Old';
    else if Treatment='C' and AgeGroup='Young' then GroupVar='C_Young';
    else if Treatment='C' and AgeGroup='Old' then GroupVar='C_Old';
    datalines;
A Young 25 A Young 28 A Young 30 A Young 22 A Young 26
A Old   32 A Old   35 A Old   38 A Old   30 A Old   33
B Young 18 B Young 20 B Young 22 B Young 19 B Young 21
B Old   28 B Old   30 B Old   32 B Old   27 B Old   29
C Young 30 C Young 32 C Young 34 C Young 31 C Young 33
C Old   40 C Old   42 C Old   45 C Old   38 C Old   41
;
run;

proc sql noprint;
create table treatment_data2 as
select *,count(*) as n from treatment_data group by Treatment,GroupVar;
select min(value)-1 into :min from treatment_data;
quit;
data treatment_data2;
length Treatment $ 20;
 set treatment_data2;
 by Treatment GroupVar;
 min=&min.;
 if not first.GroupVar then call missing(n);

 if Treatment='B' then Treatment='  B';
   else  if Treatment='C' then Treatment=' C';

run;

%sganno
data sganno;  /*display COUNT or N at south-west corner */
 %SGTEXT(
     LABEL="N",
     DRAWSPACE="WALLPERCENT" ,X1=-2,Y1=2.5,
     JUSTIFY= "RIGHT" ,
     TEXTCOLOR="black" ,
/*     TEXTSIZE= n units,*/
     RESET="ALL"
     )
run;





/* Create box plot with custom styling */
ods graphics on / attrpriority=none;

proc sgplot data=treatment_data2  sganno=sganno;


    title "Box Plot with Custom Treatment Colors and Age Patterns";
 styleattrs 
               datafillpatterns=(L1  X1)
			   DATASYMBOLS=( circlefilled squarefilled  )
				datacontrastcolors=(black); /* Young=L1, Old=X1 for all treatments */
   


 vbox Value / category=Treatment 
                 group=AgeGroup 
                 groupdisplay=cluster 
                 nooutliers fillpattern fillattrs=(color=white)
                  name='x';
    
 scatter x=Treatment y=min/group=AgeGroup groupdisplay=cluster datalabel=n datalabelpos=left clusterwidth=0.7 discreteoffset=-0.1 markerattrs=(size=0);
/*xaxistable n/x=Treatment class=AgeGroup classdisplay=cluster location=inside  ;*/

    xaxis label="Treatment" colorbands=even;
    yaxis label="Measurement Value" grid;
    
    /* Custom legend */
    keylegend 'x'/ title="Age Group" 
               position=topright 
               across=1;
run;

Ksharp_0-1747274113469.png

 

hackathon24-white-horiz.png

The 2025 SAS Hackathon Kicks Off on June 11!

Watch the live Hackathon Kickoff to get all the essential information about the SAS Hackathon—including how to join, how to participate, and expert tips for success.

YouTube LinkedIn

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
  • 39 replies
  • 3131 views
  • 13 likes
  • 6 in conversation
--> --> -->
OSZAR »