BookmarkSubscribeRSS Feed
🔒 This topic is solved and locked. Need further help from the community? Please sign in and ask a new question.
djbateman
Lapis Lazuli | Level 10

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;

1 ACCEPTED SOLUTION

Accepted Solutions
Reeza
Super User

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);

View solution in original post

4 REPLIES 4
Reeza
Super User

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?)

djbateman
Lapis Lazuli | Level 10

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.

Reeza
Super User

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);

djbateman
Lapis Lazuli | Level 10

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!

sas-innovate-2024.png

Don't miss out on SAS Innovate - Register now for the FREE Livestream!

Can't make it to Vegas? No problem! Watch our general sessions LIVE or on-demand starting April 17th. Hear from SAS execs, best-selling author Adam Grant, Hot Ones host Sean Evans, top tech journalist Kara Swisher, AI expert Cassie Kozyrkov, and the mind-blowing dance crew iLuminate! Plus, get access to over 20 breakout sessions.

 

Register now!

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.

Click image to register for webinarClick image to register for webinar

Classroom Training Available!

Select SAS Training centers are offering in-person courses. View upcoming courses for:

View all other training opportunities.

Discussion stats
  • 4 replies
  • 1100 views
  • 0 likes
  • 2 in conversation