I'm attempting to automate graphing of outcome variable mean values & error bars by embedding proc sgplot inside a macro do loop.
Unfortunately my code is only plotting the first variable over and over when it loops rather than plotting all 28 variables.
Here's a sample of my code & data for 2 variables that replicates the issue.
Thoughts what I'm doing wrong?
data macrovars3;
input trmt $ prez1 prez2 postz1 postz2;
cards;
No 0 1 0 0
No 1 1 0 1
No 1 0 1 0
No 1 0 1 0
No 0 0 0 0
No 0 0 0 0
No 0 0 0 0
No 0 0 0 0
No 0 0 0 0
Y 1 0 1 0
Y 1 1 1 0
Y 1 1 0 1
Y 1 1 1 1
Y 0 0 0 0
Y 0 0 1 0
Y 1 0 0 0
Y 1 1 0 1
Y 1 1 0 1
Y 1 0 1 0
Y 1 0 1 0
;
run;
/* Macro variables for medical diagnosis categories */
%let z1 = CHF;
%let z2 = VALVE;
/* Macro graphing loop */
%macro RunPlot(DSName, NumVars);
%do i=1 %to &NumVars;
/* Stack datasets for pre and post outcomes and diagnosis, create period indicator. */
data cohort_match_real_data_ge0_pre (keep=trmt period diagnosis);
set &DSName;
length period $4.;
period = "Pre";
diagnosis = prez&i;
run;
data cohort_match_real_data_ge0_post (keep=trmt period diagnosis);
set &DSName;
length period $4.;
period = "Post";
diagnosis = postz&i;
run;
data cohort_match_prepost;
set cohort_match_real_data_ge0_pre cohort_match_real_data_ge0_post;
run;
/* Calculate the means and the standard errors. */
proc sort data=cohort_match_prepost out=cohort_match_prepost_2;
by trmt period;
run;
ods trace on;
proc means data=cohort_match_prepost_2;
by trmt period;
var diagnosis;
ods output summary=meansout;
run;
/* Calculate the upper and lower error bar values. */
data meansout;
set meansout;
lowerCI_diagnosis = diagnosis_Mean - 1.96*diagnosis_StdDev/diagnosis_N**.5;
upperCI_diagnosis = diagnosis_Mean + 1.96*diagnosis_StdDev/diagnosis_N**.5;
run;
/* Plot mean values of pre and post diagnoses */
ods listing close;
ods html file='scatterplot.html' path='.' style=styles.statistical;
ods graphics / reset attrpriority=color width=600px height=400px imagefmt=gif;
proc sgplot data=meansout;
scatter x=period y=diagnosis_Mean / group=trmt
yerrorlower=lowerCI_diagnosis
yerrorupper=upperCI_diagnosis
markerattrs=(symbol=CircleFilled);
series x=period y=diagnosis_Mean / group=trmt lineattrs=(thickness=2);
yaxis grid gridattrs=(color=white);
xaxis grid gridattrs=(color=white pattern=shortdash) offsetmin=0.2 offsetmax=0.2;
styleattrs backcolor=CXFFFFFF wallcolor=CXE0E0E0;
/* keylegend "pre" "post";*/
title1 "Plot pre_&&z&i and post_&&z&i Means with Standard Error Bars";
run;
ods html close;
ods listing;
%end;
%mend;
%RunPlot(macrovars3, 2)
I think you need to change the ODS HTML as shown below
ods html file="scatterplot_&i..html" path='.' style=styles.statistical;
and also remove the RESET option from ODS GRAPHICS.
From now on, when you are trying to debug macros, you need to turn on this option
options mprint;
This makes the LOG much more readable and makes clear that CHF is plotted and later VALVE is plotted, as the TITLE statements in the LOG indicate this clearly.
The problem is here:
ods html file='scatterplot.html' path='.' style=styles.statistical;
Plots always go to the same .html file, and so the first one is overwritten by the next one, and so on.
You might want to do yourself a favor and name your variables PRE_CHF and POST_CHF and so on, instead of the much less meaningful prez1 and postz1 and so on.
I think you need to change the ODS HTML as shown below
ods html file="scatterplot_&i..html" path='.' style=styles.statistical;
and also remove the RESET option from ODS GRAPHICS.
SAS Innovate 2025 is scheduled for May 6-9 in Orlando, FL. Sign up to be first to learn about the agenda and registration!
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.
Ready to level-up your skills? Choose your own adventure.