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

Posts: 1,318

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
Posts: 8,089

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

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

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

Posts: 1,318

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;``````
Discussion stats
• 3 replies
• 284 views
• 0 likes
• 3 in conversation