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

Similar to what was apparently possible with SAS GCHART (https://v8doc.sas.com/sashtml/gref/bychap.htm), I would like to customize the annotation for the output from each BY group by incuding the BY variable in the sganno data set.

 

For example, in the following chart, I would only like to show the Female line in the Female chart and the Male line in the Male chart ... 

 

data Line;
  infile datalines dlm='#';
  length id $ 1
			label $ 27
         textcolor $ 9
         linecolor $ 9
		y1space $ 9
		y2space $ 9;

  input id $ function $ x1 y1 label $ x2 y2 textcolor linecolor y1space $ y2space $;
datalines;
F  # text # 50 # 63 # F Average 61 Inches # . # . # blue #  # datavalue # datavalue #
F # line # 10 # 61 #   # 99 # 61 #   # blue # datavalue # datavalue #
M # text # 20 # 66 # M Average 64 Inches # . # . # blue # # datavalue # datavalue #
M # line # 10 # 64 #   # 99 # 64 #   # blue # datavalue # datavalue #
;
run;
proc sort data=sashelp.class out=class;
by sex;
run;
proc sgplot data=class sganno=Line;
by sex;
 scatter x=weight y=height;
 yaxis min=55 max=75;
run;

ByAnno.png

 

Note this is my current workaround (macro processing with a do loop), however it would be great to know if this possible by using the BY statement.

/*See: http://support.sas.com/kb/26/155.html*/
/*http://blogs.sas.com/content/publishing/2015/01/30/sas-authors-tip-getting-the-macro-language-to-perform-a-do-loop-over-a-list-of-values/*/
proc sql noprint;
  select distinct sex into : sex_list separated by ' ' from class;
quit;
%macro plotBy(values);    
                                                                                                                
     /* Count the number of values in the string */                                                                                                                                   
     %let count=%sysfunc(countw(&values)); 

     /* Loop through the total number of values */                                                                                         
     %do i = 1 %to &count;                                                                                                              
      %let value=%qscan(&values,&i,%str( ));                                                                                            
        
		   proc sgplot data=class(where=(sex="&value")) sganno=Line(where=(id="&value"));
	 scatter x=weight y=height;
	 yaxis min=55 max=75;
	run;
 
     %end;                                                                                                                              
                                                                                                                                        
%mend; 
%plotBy(&sex_list); 

 

 

Many thanks,

Marie

1 ACCEPTED SOLUTION

Accepted Solutions
Jay54
Meteorite | Level 14

When you are using SGPLOT, often you can get stuff done with statements and may not need annotate.  In this case, you can add the mean values to the original data set by 'Sex' and then use a reference line statement to get the result.  You can add additional data to the data set and display the text you need.  Using statement overlays is more robust, as such reference line values are sent to the axis for proper scaling.  Annotated values are not.

 

SGPlot annotation does not have BY variable support.  The need has not come up due to its different architecture.  However, if the need arises, we can add that feature in a future release.

 

data class;
  set sashelp.class end=last;
  output;

  if last then do;
    call missing (name, sex, age, height, weight);
    sex='M'; Avg=64; output;
    sex='F'; Avg=61; output;
  end;
run;

 

proc sort data=class out=class2;
by sex;
run;

 

proc sgplot data=class2 uniform=yscale;
  by sex;
  scatter x=weight y=height;
  refline avg / label;
run;

 

ScatterRefBySex.png

 

View solution in original post

6 REPLIES 6
Jay54
Meteorite | Level 14

When you are using SGPLOT, often you can get stuff done with statements and may not need annotate.  In this case, you can add the mean values to the original data set by 'Sex' and then use a reference line statement to get the result.  You can add additional data to the data set and display the text you need.  Using statement overlays is more robust, as such reference line values are sent to the axis for proper scaling.  Annotated values are not.

 

SGPlot annotation does not have BY variable support.  The need has not come up due to its different architecture.  However, if the need arises, we can add that feature in a future release.

 

data class;
  set sashelp.class end=last;
  output;

  if last then do;
    call missing (name, sex, age, height, weight);
    sex='M'; Avg=64; output;
    sex='F'; Avg=61; output;
  end;
run;

 

proc sort data=class out=class2;
by sex;
run;

 

proc sgplot data=class2 uniform=yscale;
  by sex;
  scatter x=weight y=height;
  refline avg / label;
run;

 

ScatterRefBySex.png

 

mduarte
Quartz | Level 8

Thank-you for your comprehensive reply.  That SGPlot annotation does not have BY variable support answers my question.  I hadn't thought of the solution you provided but not sure if it would apply to my "real" problem.  The example I gave was fabricated and not what I am working on.  In my case, I am doing something similar to: vbar = Australian State (e.g.  QLD, NSW ...), the BY variable is operation type (e.g. hip replacement, ...) and the refline is national average (i.e., not the "by" variable, or state, average).  Also, I haven't hardcoded the national averages, but taking them from dataset itself.   

Jay54
Meteorite | Level 14

I used hard coded values for convenience to suggest how to use SGPLOT for such a graph.  Clearly, one should use something like PROC MEANS and merge the data.  I beleive you will be able to use the "layered" SGPLOT approach for your real use case.  However, using GPLOT with the annotation is perfectly fine too.  

mduarte
Quartz | Level 8
Nice - confirming that your solution works for the real use case as well! Thanks again.
Jay54
Meteorite | Level 14

If the average line is a national average, not part of the BY variable, it is likely straightforward.  You could compute the average into a macro variable and use that with the REFLINE statement.

SAS Innovate 2025: Register Now

Registration is now open for SAS Innovate 2025 , our biggest and most exciting global event of the year! Join us in Orlando, FL, May 6-9.
Sign up by Dec. 31 to get the 2024 rate of just $495.
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
  • 6 replies
  • 3202 views
  • 2 likes
  • 2 in conversation