BookmarkSubscribeRSS Feed
Sam28041977
Calcite | Level 5

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. 

Capture.JPG

%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));

 

 

Astounding
PROC Star

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?

Sam28041977
Calcite | Level 5

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

Tom
Super User Tom
Super User

@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-wordmark-2025-midnight.png

Register Today!

Join us for SAS Innovate 2025, our biggest and most exciting global event of the year, in Orlando, FL, from May 6-9. Sign up by March 14 for just $795.


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
  • 18 replies
  • 2012 views
  • 1 like
  • 6 in conversation