DATA Step, Macro, Functions and more

DOSUBL : Problem when using macro variables after CALL EXECUTE

Reply
Contributor
Posts: 23

DOSUBL : Problem when using macro variables after CALL EXECUTE

Hi everyone, 

 

I've been trying to write a macro using DOSUBL to return a string so I can use it directly in DATA Step. Inside the DOSUBL block, I call another macro using CALL EXECUTE which will return 2 macro variables.

 

Here is the macro which returns 2 macro variables :

%macro Binomial_p(r,n,alpha=0.05);

/* Create data set param6 */
data param6;
	r = &r.;
    n = &n.;
    alpha = &alpha.;
    p = r/n;
	q = 1 - p;
    z = probit(1-alpha/2);
    output;
    max_idx = alpha/2;
	min_idx = 1 - alpha/2;

	do j = 0.000001 to 0.999999 by 0.00001;
		if (r > 0 and r < n) then a2 = 0.5*probbnml(j,n,r-1) + 0.5*probbnml(j,n,r);
		output;
	end;
run;

/* Create data set min & max */
proc sql;
	create table max as
	select max(j) as upper6
	from param6		
	where a2 > max_idx and r > 0 and r < n;

	create table min as
	select min(j) as lower6
	from param6		
	where a2 <= min_idx and r > 0 and r < n;
quit;

/* Store lower6 & upper6 into macro variables for future use */
%global lower6 upper6;
data ci6;
	merge param6(obs=1) min max;
	if r = 0 then do;
		lower6 = 0;
		upper6 = 1 - alpha**(1/n);
	end;
	if r = n then do;
		lower6 = alpha**(1/n);
		upper6 = 1;
	end;
	call symputx("lower6",lower6);
	call symputx("upper6",upper6);
run;

/* Delete unnecessary data sets */
proc datasets nolist; 
	delete param6 min max ci6; 
run;

%mend Binomial_p;

/*
%Binomial_p(r=81,n=263,alpha=0.05);
%put lower6=&lower6. upper6=&upper6.;
*/

 Here is the main DOSUBL block :

%macro CI_Proportion(r,n,method,alpha=0.05);

%local ci;
%let rc = %sysfunc(dosubl(%str(

data _null_;
	/* Define some values */
    r = &r.;
    n = &n.;
    alpha = &alpha.;
    p = r/n;
	q = 1 - p;
    z = probit(1-alpha/2);
	/* 6.  Binomial-based, Mid-p (Binomial_p) */
	if &method. = "Binomial_p" then do;
		call execute('%Binomial_p(r=&r.,n=&n.,alpha=&alpha.);');
		lower = &lower6.;
		upper = &upper6.;
	end;
	/* Store ci into macro variable */
	ci = strip(put(r,10.)) || " " || strip(put(p,10.4)) || "(" || strip(put(lower,10.4)) || "-" || strip(put(upper,10.4)) || ")";
	call symputx("ci",ci);
run;

)));
/* Return macro variable ci */
&ci.

%mend CI_Proportion;

%put %CI_Proportion(r=81,n=263,method="Binomial_p",alpha=0.05);

I ran into 2 errors :

ERROR 386-185: Expecting an arithmetic expression.
ERROR 200-322: The symbol is not recognized and will be ignored.
386: LINE and COLUMN cannot be determined.
WARNING: Apparent symbolic reference LOWER6 not resolved.
WARNING: Apparent symbolic reference UPPER6 not resolved.

For the second error, I think I can't use 2 macro variables after CALL EXECUTE because they don't exist yet. Is it correct ? 

For the first one, I couldn't find where is the error.

 

Thanks in advance for any input !!!

Trusted Advisor
Posts: 1,301

Re: DOSUBL : Problem when using macro variables after CALL EXECUTE

You cannot use call execute with a macro like this. You would have to run it as a dosubl also. You should really rethink your entire design here. Not good.
Super User
Super User
Posts: 7,060

Re: DOSUBL : Problem when using macro variables after CALL EXECUTE

Watch out for inteaction between local and global symbol tables when using DOSSUBL.

See this thread.

https://communities.sas.com/t5/Base-SAS-Programming/DOSUBL-scope-of-returned-macro-variables/m-p/138...

 

Trusted Advisor
Posts: 1,301

Re: DOSUBL : Problem when using macro variables after CALL EXECUTE

To build, somewhat, on your post from yesterday, try using PROC FCMP

 

proc fcmp;

subroutine Binomial_p(r, n, alpha, upper6, lower6);
   outargs upper6, lower6;
   p = r/n;
   q = 1 - p;
   z = probit(1-alpha/2);

   if r = 0 then do;
      lower6 = 0;
	  upper6 = 1 - alpha**(1/n);
   end;
   else if r = n then do;
      lower6 = alpha**(1/n);
	  upper6 = 1;
   end;
   else do;
      length max_idx min_idx rc j a2 8;
      max_idx = alpha/2;
      min_idx = 1 - alpha/2;
      
      declare hash h(ordered:'d');
      declare hiter hi('h');
         rc = h.definekey('j');
         rc = h.definedata('a2');
      rc = h.definedone();

      do j = 0.000001 to 0.999999 by 0.00001;
         if (r > 0 and r < n) then do;
	        a2 = 0.5*probbnml(j,n,r-1) + 0.5*probbnml(j,n,r);
		    if a2 <= a2 > max_idx then rc = h.add();
	     end;
      end;

      rc = hi.first();
      if a2 > max_idx then upper6 = j;
      rc = hi.last();
	  if a2 <= min_idx then lower6 = j;
   end;
endsub;

function CI_Proportion(r, n, method $, alpha) $;
   p = r/n;
   q = 1 - p;
   z = probit(1-alpha/2);

   length upper lower 8;
   if method = "Binomial_p" then call Binomial_p(r,n,alpha,upper,lower);

   ci = strip(put(r,10.)) || " " || strip(put(p,10.4)) || "(" || strip(put(lower,10.4)) || "-" || strip(put(upper,10.4)) || ")";
   return(ci);
endsub;

ci_proportion = CI_Proportion(81,263,"Binomial_p",0.05);
put ci_proportion=;

quit;
Ask a Question
Discussion stats
  • 3 replies
  • 243 views
  • 0 likes
  • 3 in conversation