BookmarkSubscribeRSS Feed
bkq32
Quartz | Level 8
data have;
input id $3. mean_arm mean_leg diff_arm diff_leg upper_arm upper_leg lower_arm lower_leg reader_arm reader_leg;
cards;
ABC 878 787 2 1 8 9 -4 -3 872 788
DEF 600 500 7 4 10 11 -8 -7 590 501
GHI 300 200 12 4 11 8 -11 -10 299 202
;
run;

Using a data set like the one above with several body measurements (body part specified in the suffix of the variable name), I made a macro for PROC SGPLOT which plots DIFF_&thissuffix against MEAN_&thissuffix for each body part:

 

%macro graph(suffixes= );
 %let nsuffix=%sysfunc(countw(&suffixes));

 %do i= 1 %to &nsuffix;
 %let thissuffix=%scan(&suffixes,&i,%str( ));

proc sgplot data=have;
 scatter x=mean_&thissuffix y=diff_&thissuffix;
 run; quit;
 %end;
%mend;

%graph (suffixes= arm leg);

How do I add a REFLINE statement that makes horizontal lines at LOWER_&thissuffix and UPPER_&this.suffix? For a particular body part, the values of LOWER_&thissuffix are the same for all records, as are those for UPPER_&thissuffix.

4 REPLIES 4
ed_sas_member
Meteorite | Level 14

Hi @bkq32 ,

 

Could you please provide more information about what does lower_&thissuffix and upper_&thissuffix represent?

 

I think you should explore the following options in the SCATTER statement of your PROC SGPLOT

proc sgplot data=have;
 scatter x=mean_&thissuffix y=diff_&thissuffix / yerrorlower=lower_&thissuffix yerrorupper=upper_&thissuffix;
 run; quit;

"yerrorlower" specifies a variable that contains the lower endpoints for the Y error bars

"yerrorupper" specifies a variable that contains the upper endpoints for the Y error bars.

in the same way, you have also xerrorupper and yerrorupper

 

Best,

 

bkq32
Quartz | Level 8

Hi @ed_sas_member ,

 

I'm making a Bland-Altman plot where I compare a reader's values with a gold standard. LOWER_&THISSUFFIX and UPPER_&THISSUFFIX represent the lower/upper limits of agreement between the two, calculated as:

 

[(mean difference between reader and gold for a body part) - 1.96(standard deviation of the differences for a body part)]

[(mean difference between reader and gold for a body part) + 1.96(standard deviation of the differences for a body part)]

 

Since LOWER_ARM (as an example) has the same value for all records, I'd like one horizontal line rather than error bars for each of my observations.

PaigeMiller
Diamond | Level 26

@bkq32 wrote:
data have;
input id $3. mean_arm mean_leg diff_arm diff_leg upper_arm upper_leg lower_arm lower_leg reader_arm reader_leg;
cards;
ABC 878 787 2 1 8 9 -4 -3 872 788
DEF 600 500 7 4 10 11 -8 -7 590 501
GHI 300 200 12 4 11 8 -11 -10 299 202
;
run;

Using a data set like the one above with several body measurements (body part specified in the suffix of the variable name), I made a macro for PROC SGPLOT which plots DIFF_&thissuffix against MEAN_&thissuffix for each body part:

 

%macro graph(suffixes= );
 %let nsuffix=%sysfunc(countw(&suffixes));

 %do i= 1 %to &nsuffix;
 %let thissuffix=%scan(&suffixes,&i,%str( ));

proc sgplot data=have;
 scatter x=mean_&thissuffix y=diff_&thissuffix;
 run; quit;
 %end;
%mend;

%graph (suffixes= arm leg);

How do I add a REFLINE statement that makes horizontal lines at LOWER_&thissuffix and UPPER_&this.suffix? For a particular body part, the values of LOWER_&thissuffix are the same for all records, as are those for UPPER_&thissuffix.


Somewhere, you have to calculate LOWER_&thissuffix and UPPER_&thissuffix before your run PROC SGPLOT.

 

In fact, this is a common mistake. First, you have to figure out how to do this calculation and create a working REFLINE statement without using macros, for one plot. You haven't done this. Once you create such a working version of SAS code without macros, then creating a working macro which includes the desired REFLINE statement inside PROC SGPLOT ought to be easy enough.

 

So, task number 1, create code that does the desired SGPLOT with REFLINEs without macros, for a single instance of the plot.

--
Paige Miller
bkq32
Quartz | Level 8

Thanks, Paige. I did that here and it created the desired plot for ARM.

 

data have2;
 set have;

 upper_arm=meandiff_arm+1.96*stddiff_arm;
 lower_arm=meandiff_arm-1.96*stddiff_arm;

 upper_leg=meandiff_leg+1.96*stddiff_leg;
 lower_leg=meandiff_leg-1.96*stddiff_leg;
run;

proc sgplot data=have2;
 scatter x=mean_arm y=diff_arm;
 refline 0 -7.592 2.992;
 needle x=reader_arm
        y=diff_arm / baseline=0;
 yaxis values=(-8 to 8 by 2);
 title "Bland-Altman Plot (arm)";
run; quit;

I'm thinking the next step is to use CALL SYMPUT to store the values of UPPER_: and LOWER_:, and then call it in the REFLINE statement? I'm not too familiar with CALL SYMPUT yet.

SAS Innovate 2025: Save the Date

 SAS Innovate 2025 is scheduled for May 6-9 in Orlando, FL. Sign up to be first to learn about the agenda and registration!

Save the date!

Mastering the WHERE Clause in PROC SQL

SAS' Charu Shankar shares her PROC SQL expertise by showing you how to master the WHERE clause using real winter weather data.

Find more tutorials on the SAS Users YouTube channel.

Discussion stats
  • 4 replies
  • 1112 views
  • 0 likes
  • 3 in conversation