hello,
the algorithme that is described bellow. my full macro is bellow also. the input of the macro is a 2 columns datasets (lab and result). this algorithm detect labs with deviations.
%macro prof(var=,data=);
data &data.;
set anadat.&data.;
if &var ne .;
run;
proc means data=&data.;
where &var. ne .;
var &var.;
output out=a median=x;
run;
PROC SQL;
SELECT x INTO:X0 FROM a;
QUIT;
PROC SQL;
CREATE TABLE &var. AS SELECT Lab, &var. as &var.0, (ABS(&var.-&x0.)) AS DIFF0 FROM &data.;
QUIT;
proc means data=&var. median;
var Diff0;
output out=b median=s;
run;
PROC SQL;
SELECT (S*1.483) INTO:S0 FROM B;
SELECT (S*1.483*1.5) INTO:sigma0 FROM B;
QUIT;
DATA &var.S0;
ITER=0;X=ROUND(&X0.,.01);S=ROUND(&S0.,.01); Sigma=ROUND(&sigma0.,.01);
X_=&X0;S_=&S0; Sigma_=&sigma0; OUTPUT;
RUN;
DATA &VAR.;
SET &VAR.;
DROP DIFF0;
RUN;
%do i=1 %to 100;
%put %cmpres(&&&&x%eval(&i.-1));
data &var.;
SET &var.;
if &var.0 ne . and &var.0<(%cmpres(&x%eval(&i.-1))-%cmpres(&sigma%eval(&i.-1))) then &var.&i.=(%cmpres(&x%eval(&i.-1))-%cmpres(&sigma%eval(&i.-1)));
else if &var.0 ne . and &var.0>(%cmpres(&x%eval(&i.-1))+%cmpres(&sigma%eval(&i.-1))) then &var.&i.=(%cmpres(&x%eval(&i.-1))+%cmpres(&sigma%eval(&i.-1)));
else if &var.0 ne . then &var.&i.=&var.0;
run;
PROC SQL;
SELECT mean(&var.&i.) INTO: x&i. FROM &var.;
SELECT (1.134*std(&var.&i.)) INTO: s&i. FROM &var.;
SELECT (1.5*1.134*std(&var.&i.)) INTO: sigma&i. FROM &var.;
QUIT;
DATA &var.S&i.;
ITER=&i.;X=ROUND(&&X&i.,.01);S=ROUND(&&S&i.,.01); Sigma=ROUND(&&sigma&i.,.01);
X_=&&X&i.;S_=&&S&i.; Sigma_=&&sigma&i.;OUTPUT;
RUN;
%if &i.>1 %then %Do;
DATA _NULL_;
CALL symput ('x_',round(&&x&i.,.01));
CALL symput ('x__',round(%cmpres(&x%eval(&i.-1)),.01));
CALL symput ('x___',round(%cmpres(&x%eval(&i.-2)),.01));
CALL symput ('s_',round(&&s&i.,.01));
CALL symput ('s__',round(%cmpres(&s%eval(&i.-1)),.01));
CALL symput ('s___',round(%cmpres(&s%eval(&i.-2)),.01));
RUN;
%if (&x_. eq &x__.) and (&s_. eq &s__.) and (&x_. eq &x___.) and (&s_. eq &s___.)%then %do;
DATA &var._;
SET &var.;
FORMAT Z 5.2 Z_ $10. BIAS 5.2 BIAS_ $10. X S 5.2;
X=&&x&i.;
S=&&s&i.;
IF &var.0 NE . THEN Z=(&var.0-&&x&i.)/&&s&i.;
IF &var.0 NE . THEN BIAS=(&var.0-&&x&i.);
if Z<-3 or z>3 then DO;
IF Z NE . THEN Z_=compbl(put(Z,5.2)!!"A");
IF BIAS NE . THEN BIAS_=compbl(put(BIAS,5.2)!!"A");
end;
else if Z<-2 or z>2 then DO;
IF Z NE . THEN Z_=compbl(put(Z,5.2)!!"W");
IF BIAS NE . THEN BIAS_=compbl(put(BIAS,5.2)!!"W");
end;
else DO;
Z_=put(Z,5.2);
BIAS_=put(BIAS,5.2);
end;
label Lab="Lab" X="Assigned value (Robust Estimate)" S="Standard Deviation (Robust Estimate)"
BIAS="Estimate of Lab Bias" BIAS_="Estimate of Lab Bias (With Flag)"
Z="Z Score" Z_="Z Score (With Flag)";
KEEP Lab &VAR.0 X S BIAS BIAS_ Z Z_;
run;
proc sql;
create table anadat.&var. as select Lab, &var.0, X, S, BIAS, BIAS_, Z, Z_
from &var._;
quit;
DATA &var.S;
SET &var.S0 %do g=1 %to &i.; &var.s&g. %end;;
RUN;
%goto exit;
%end;
%end;
%end;
%exit:
/*proc datasets library=work;
delete &var.S: S:;
quit; */
%mend prof;
%prof(var=WR10_S,data=%str(DATA));
So in some cases, you fixed the problem, changing & to &&. (In one place, you even used &&&& which doesn't hurt anything, since &&&& resolves to && anyway.)
In a bunch of other places you left a single & where you require &&. So you are still getting the error message, but macro language is not that helpful in describing where the error occurs. Do you need help in understanding when to change & to && so that the macro expressions resolve correctly?
hello Astounding,
adding & or && or &&& don't resolved the problem.
But what I wanted to explain from the begining is that I don't understand the warning because the macros variable resolve correctly whatever the number of &.
I provided a small macro that show that the result is correct but I still have a warning.
krs
@Sam28041977 wrote:
hello Astounding,
adding & or && or &&& don't resolved the problem.
But what I wanted to explain from the begining is that I don't understand the warning because the macros variable resolve correctly whatever the number of &.
I provided a small macro that show that the result is correct but I still have a warning.
krs
When the macro processor sees a macro variable reference it replaces the reference with the value of the macro variable. But when you reference a macro variable that doesn't exist the macro processor generates a warning and then DOES NOTHING with the incoming text.
Because you are then using the resulting text in a place where the macro processor will re-process the resulting string is why it ultimately generates the desired result. The second time it processes it the macro processor sees a valid macro variable reference.
You can see the same result with code like this.
%let x2=TWO;
%put &x%eval(1+1);
%Put %unquote(&x%eval(1+1));
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.