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 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!

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
  • 1734 views
  • 1 like
  • 6 in conversation