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 !!!
Watch out for inteaction between local and global symbol tables when using DOSSUBL.
See this thread.
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;
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.