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 2024

Innovate_SAS_Blue.png

Registration is open! SAS is returning to Vegas for an AI and analytics experience like no other! Whether you're an executive, manager, end user or SAS partner, SAS Innovate is designed for everyone on your team. Register for just $495 by 12/31/2023.

If you are interested in speaking, there is still time to submit a session idea. More details are posted on the website. 

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.

Get the $99 certification deal.jpg

 

 

Back in the Classroom!

Select SAS Training centers are offering in-person courses. View upcoming courses for:

View all other training opportunities.

Discussion stats
  • 6 replies
  • 2283 views
  • 1 like
  • 2 in conversation