## Call a Macro in a Data Step Loop

Solved
Regular Contributor
Posts: 247

# Call a Macro in a Data Step Loop

My problem has two questions:

1.  Can a macro be called in a data step?

2.  If so, how can I loop through in a single data step that will add a new line to the data table and use a value in the table as an input parameter to that macro?

Here is a general example of what I want to do:

ITERATION = the number of times I have gone through the loop

COMPARE = the variable used to compare with RESULT

MINVAL = the minimum possible value of VALUE; set at 0 on first iteration.  On all other iterations, if RESULT[i-1] < COMPARE[i-1], then MINVAL = MINVAL[i-1]; else MINVAL = VALUE[i-1]

MAXVAL = the maximum possible value of VALUE; set at 1 on first iteration.  On all other iterations, if RESULT[i-1] > COMPARE[i-1], then MAXVAL = MAXVAL[i-1]; else MAXVAL = VALUE[i-1]

VALUE = the midpoint between MINVAL and MAXVAL (derived as:  MINVAL + (MAXVAL-MINVAL) / 2)

RESULT = The returned value from a macro call using VALUE as an input parameter

ITERATIONCOMPAREMINVALMAXVALVALUERESULT
10.90000010.50.00088
20.9000000.50.250.46054
30.9000000.250.1250.93546
40.900000.1250.250.18750.75793
50.900000.1250.18750.156250.86567
60.900000.1250.156250.1406250.90512
70.900000.1406250.156250.14843750.88658
80.900000.1406250.14843750.144531250.89614
90.900000.1406250.144531250.1425781250.90070
100.900000.1425781250.144531250.1435546880.89844
110.900000.1425781250.1435546880.1430664060.89958
120.900000.1425781250.1430664060.1428222660.90014
130.900000.1428222660.1430664060.1429443360.89986
14

0.90000

0.1428222660.1429443360.1428833010.90000

In the end, I just need the last value stored in VALUE.  I don't need this data table, although it would be nice to retain to make sure that it is doing what I want it to do.

Here is my code so far.  It will give me the first line, but I am at a loss as to where to go from here.  I am not sure how to implement the DO loop with what I am trying to do.

/***  Find the power  ***/

%macro kappa_power(rate1=,rate2=,kappa=,kappa0=,n=,alpha=0.05,sided=2);

data kappa;

p1_=&rate1.;

p_1=&rate2.;

p2_=1-p1_;

p_2=1-p_1;

pe=p1_*p_1+p2_*p_2;

p0=&kappa.*(1-pe)+pe;

p22=(p0-p1_+p_2)/2;

p11=p0-p22;

p12=p1_-p11;

p21=p_1-p11;

A=(p11*((1-pe)-(p1_+p_1)*(1-p0))**2)+(p22*((1-pe)-(p2_+p_2)*(1-p0))**2);

B=(1-p0)**2*(p12*(p_1+p2_)**2+p21*(p_2+p1_)**2);

C=(p0*pe-2*pe+p0)**2;

Q=(1-pe)**-4*(A+B-C);

output;

call symputx("Q1",Q);

run;

data kappa0;

set kappa (keep=p1_ p_1 p2_ p_2 pe);

p0=&kappa0.*(1-pe)+pe;

p22=(p0-p1_+p_2)/2;

p11=p0-p22;

p12=p1_-p11;

p21=p_1-p11;

A=(p11*((1-pe)-(p1_+p_1)*(1-p0))**2)+(p22*((1-pe)-(p2_+p_2)*(1-p0))**2);

B=(1-p0)**2*(p12*(p_1+p2_)**2+p21*(p_2+p1_)**2);

C=(p0*pe-2*pe+p0)**2;

Q=(1-pe)**-4*(A+B-C);

output;

call symputx("Q0",Q);

run;

%global power;

data _null_;

Zb=(((&kappa.-&kappa0.)*sqrt(&n.)) - (quantile('NORMAL',1-(&alpha./&sided.))*sqrt(&Q0.))) / sqrt(&Q1.);

power=probnorm(Zb);

call symputx("power",power);

run;

%put Power = &power.;

%mend kappa_power;

data iteration;

i=1;

phat=.90000;

minkap=0;

maxkap=1;

kappa0=minkap+(maxkap-minkap)/2;

output;

run;

proc sql;

select kappa0 into :kappa0 from iteration having i=max(i);

quit;

%kappa_power(rate1=0.8,rate2=0.8,kappa=0.375,kappa0=&kappa0.,n=200,alpha=0.05,sided=1);

data power;

i=1;

power=&power.;

run;

data converge;

merge iteration power;

by i;

run;

Accepted Solutions
Solution
‎12-10-2012 11:19 AM
Super User
Posts: 23,771

## Re: Call a Macro in a Data Step Loop

You're doing a binomial search for maximum power?

I think something like the following would work, it's only sketched out, but hopefully gives you an idea.  I have to actually do some work today :smileyconfused:

Given the code you already have I think it would work, but wasn't sure how to reset the parameters for each iteration in the loop based on your data, mostly because I don't have time...

I also added in a maxiteration so you don't loop forever and good for testing. There's also a while condition to test when you get close enough to a value to determine when to stop.

Good luck.

%macro kappa_power(rate1=,rate2=,kappa=,kappa0=,n=,alpha=0.05,sided=2, maxiter=20);

%do i=1 %to &maxiter %while (error bounds here);

%if &i=1 %then %do;

data iteration;

i=1;

phat=.90000;

minkap=0;

maxkap=1;

kappa0=minkap+(maxkap-minkap)/2;

run;

%end;

%else %do;

data iteration;

i=&i;

*determine new testing value here/macro parameters here;

run;

%end;

data kappa;

p1_=&rate1.;

p_1=&rate2.;

p2_=1-p1_;

p_2=1-p_1;

pe=p1_*p_1+p2_*p_2;

p0=&kappa.*(1-pe)+pe;

p22=(p0-p1_+p_2)/2;

p11=p0-p22;

p12=p1_-p11;

p21=p_1-p11;

A=(p11*((1-pe)-(p1_+p_1)*(1-p0))**2)+(p22*((1-pe)-(p2_+p_2)*(1-p0))**2);

B=(1-p0)**2*(p12*(p_1+p2_)**2+p21*(p_2+p1_)**2);

C=(p0*pe-2*pe+p0)**2;

Q=(1-pe)**-4*(A+B-C);

output;

call symputx("Q1",Q);

run;

data kappa0;

set kappa (keep=p1_ p_1 p2_ p_2 pe);

p0=&kappa0.*(1-pe)+pe;

p22=(p0-p1_+p_2)/2;

p11=p0-p22;

p12=p1_-p11;

p21=p_1-p11;

A=(p11*((1-pe)-(p1_+p_1)*(1-p0))**2)+(p22*((1-pe)-(p2_+p_2)*(1-p0))**2);

B=(1-p0)**2*(p12*(p_1+p2_)**2+p21*(p_2+p1_)**2);

C=(p0*pe-2*pe+p0)**2;

Q=(1-pe)**-4*(A+B-C);

output;

call symputx("Q0",Q);

run;

data power;

Zb=(((&kappa.-&kappa0.)*sqrt(&n.)) - (quantile('NORMAL',1-(&alpha./&sided.))*sqrt(&Q0.))) / sqrt(&Q1.);

power=probnorm(Zb);

call symputx("power",power); * you may not need this as a macro variable anymore.

run;

*merge the values to get the data you need for values table;

data converge;

merge iteration power;

run;

*append for each run;

proc append base=value data=converge;

run;

%end;

%mend kappa_power;

%kappa_power(rate1=0.8,rate2=0.8,kappa=0.375,kappa0=&kappa0.,n=200,alpha=0.05,sided=1,  maxiter=20);

All Replies
Super User
Posts: 23,771

## Re: Call a Macro in a Data Step Loop

call execute will call macro's within a datastep.

Or you can loop through using another macro.

Another option is to use a function, ie FCMP instead of a macro.

I don't see any do loop, so not sure where you're trying to iterate, in the second last datastep (data power?)

Regular Contributor
Posts: 247

## Re: Call a Macro in a Data Step Loop

I will give you suggestions a try and see what I can come up with.  I have never heard of FCMP, but I found some documentation on it that I can read up on.

I have not tried to run the DO loop in my code yet because I wasn't sure how to implement it.  That's why you couldn't find it in my code.

Solution
‎12-10-2012 11:19 AM
Super User
Posts: 23,771

## Re: Call a Macro in a Data Step Loop

You're doing a binomial search for maximum power?

I think something like the following would work, it's only sketched out, but hopefully gives you an idea.  I have to actually do some work today :smileyconfused:

Given the code you already have I think it would work, but wasn't sure how to reset the parameters for each iteration in the loop based on your data, mostly because I don't have time...

I also added in a maxiteration so you don't loop forever and good for testing. There's also a while condition to test when you get close enough to a value to determine when to stop.

Good luck.

%macro kappa_power(rate1=,rate2=,kappa=,kappa0=,n=,alpha=0.05,sided=2, maxiter=20);

%do i=1 %to &maxiter %while (error bounds here);

%if &i=1 %then %do;

data iteration;

i=1;

phat=.90000;

minkap=0;

maxkap=1;

kappa0=minkap+(maxkap-minkap)/2;

run;

%end;

%else %do;

data iteration;

i=&i;

*determine new testing value here/macro parameters here;

run;

%end;

data kappa;

p1_=&rate1.;

p_1=&rate2.;

p2_=1-p1_;

p_2=1-p_1;

pe=p1_*p_1+p2_*p_2;

p0=&kappa.*(1-pe)+pe;

p22=(p0-p1_+p_2)/2;

p11=p0-p22;

p12=p1_-p11;

p21=p_1-p11;

A=(p11*((1-pe)-(p1_+p_1)*(1-p0))**2)+(p22*((1-pe)-(p2_+p_2)*(1-p0))**2);

B=(1-p0)**2*(p12*(p_1+p2_)**2+p21*(p_2+p1_)**2);

C=(p0*pe-2*pe+p0)**2;

Q=(1-pe)**-4*(A+B-C);

output;

call symputx("Q1",Q);

run;

data kappa0;

set kappa (keep=p1_ p_1 p2_ p_2 pe);

p0=&kappa0.*(1-pe)+pe;

p22=(p0-p1_+p_2)/2;

p11=p0-p22;

p12=p1_-p11;

p21=p_1-p11;

A=(p11*((1-pe)-(p1_+p_1)*(1-p0))**2)+(p22*((1-pe)-(p2_+p_2)*(1-p0))**2);

B=(1-p0)**2*(p12*(p_1+p2_)**2+p21*(p_2+p1_)**2);

C=(p0*pe-2*pe+p0)**2;

Q=(1-pe)**-4*(A+B-C);

output;

call symputx("Q0",Q);

run;

data power;

Zb=(((&kappa.-&kappa0.)*sqrt(&n.)) - (quantile('NORMAL',1-(&alpha./&sided.))*sqrt(&Q0.))) / sqrt(&Q1.);

power=probnorm(Zb);

call symputx("power",power); * you may not need this as a macro variable anymore.

run;

*merge the values to get the data you need for values table;

data converge;

merge iteration power;

run;

*append for each run;

proc append base=value data=converge;

run;

%end;

%mend kappa_power;

%kappa_power(rate1=0.8,rate2=0.8,kappa=0.375,kappa0=&kappa0.,n=200,alpha=0.05,sided=1,  maxiter=20);

Regular Contributor
Posts: 247

## Re: Call a Macro in a Data Step Loop

This actually makes obvious sense.  I guess I was trying to avoid using the same code that I had already written (since I often try to find the power of a Kappa statistic).  I suppose it won't take me long to copy and past it into a new macro and just loop through it rather than calling the macro over and over.  Thank you!

🔒 This topic is solved and locked.