Please what is wrong with this macro,why cant I get the data data impute_t_&p below

Accepted Solution Solved
Reply
Super Contributor
Posts: 297
Accepted Solution

Please what is wrong with this macro,why cant I get the data data impute_t_&p below

ods html close;

%macro surv(replicates=);

%do p=1 %to &replicates;

data tes_&p;

seed=-1;

  alpha1 = 2.50;

  beta1 = 2.00;

  beta2=4;

  do i = 1 to 500;

  X=ranbin(0,1,.5);

   lambdaT = 0.025; *baseline hazard;

   lambdaC= .03;  *heavy=0.15; *light=0.03;

   er=0+(0.05)*rannor(1);

    t = rand("WEIBULL", 0.75, lambdaT);  * time of event;

    c1 = rand("WEIBULL", 1.25, lambdaC) ;* time of censoring;

    c2= rand("WEIBULL", 1.50, lambdaC) ;

    if er le 0.240482 then c=c1; else c=c1;

   time = min(t, c);    * which came first?;

    censored = (c lt t);

      obs=(t lt c); * creating observation vaiable from censored when observeed obs=1;

      obs = (t lt c);

    y= alpha1 + beta1*t + er;

    if  t le 0.015072 then R=0;

      else if  t gt 0.015072 then R=1;

    y1= alpha1 +beta1*R + er;

    output;

  end;

run;

%do i=1 %to 7;

proc surveyselect data=tes_&i  method = urs sampsize = 10 OUTHITS

     reps=1 seed=123410 out=test_&i;

run;

proc means data = test_&i sum;

where obs = 0;

var censored; 

ods output summary = summary_&i;

run;

%end;

data impute_t_&p;

set summary_1 -summary_&i;;

run;

%end;

%mend surv;

%surv(replicates=10);


Accepted Solutions
Solution
‎11-08-2013 12:37 AM
Respected Advisor
Posts: 3,900

Re: For loops

You can define a macro within a macro but if you want to use the macro then you need to call it. So you would need to add %selecting; to your code.

You normally avoid to define a macro in a macro because in doing so the inner macro definition gets re-compiled for every call of the out macro. So what you would do if such a nesting is required is a construct like:

%macro inner;

   ....

%mend;

%macro outer;

     %inner;

%mend;

%outer;

Also don't forget that macro variables defined within a macro have per default a scope of local. So &i defined in macro %selecting is not available in the outer macro %surv. You need to use a %global i; in your inner macro to change this.

I also believe that at the end of a %do loop the value of &i is the upper boundary of the loop plus 1 - so "summary_&i;" would expect a data set "summary_8" - which doesn't exist.

I actually don't understand why you need macro %selecting at all. Can't you just have your %do loop as part of macro %surv?

Another option to collect data created iteratively would be:

proc append base=impute_t_&p data=summary_&i;

run;

You would have this proc append step inside your do loop. If you don't need to keep a table per iteration then you could also overwrite the summary_.. table in each operation and so using syntax like:

proc append base=impute_t_&p data=summary;

run;

Haven't really looked at the rest of the code. What you normally want to do is make your program work without a macro (so only for a single case) and only once this is working "macrotize" it.

Also: It's most of the times better to use by-group processing instead of calling a procedure multiple times with different data slices. So eventually you could combine the output from proc sureveyselect using proc append but then call proc means only once.

View solution in original post


All Replies
Respected Advisor
Posts: 3,900

Re: For loops

You can do what you want but the syntax is different (it looks like SAS and not JMP). You might want to have a read of the SAS Macro Language syntax, e.g. the syntax could be:

/* define and compile the macro */

%macro xxxx; ...%do i=1 %to 7; ... out=test_&i... %end; ...%mend;

/* call the macro */

%xxxx;

Super Contributor
Posts: 297

Re: For loops

So I can have a macro within a macro?

Super Contributor
Posts: 297

Re: For loops

THis is how my code looks like;, is this format correct, why is it that I cant get the data impute_t_&p

ods html close;

%macro surv(replicates=);

%do p=1 %to &replicates;

data tes_&p;

seed=-1;

  alpha1 = 2.50;

  beta1 = 2.00;

  beta2=4;

  do i = 1 to 500;

  X=ranbin(0,1,.5);

   lambdaT = 0.025; *baseline hazard;

   lambdaC= .03;  *heavy=0.15; *light=0.03;

   er=0+(0.05)*rannor(1);

    t = rand("WEIBULL", 0.75, lambdaT);  * time of event;

    c1 = rand("WEIBULL", 1.25, lambdaC) ;* time of censoring;

    c2= rand("WEIBULL", 1.50, lambdaC) ;

    if er le 0.240482 then c=c1; else c=c1;

   time = min(t, c);    * which came first?;

    censored = (c lt t);

      obs=(t lt c); * creating observation vaiable from censored when observeed obs=1;

      obs = (t lt c);

    y= alpha1 + beta1*t + er;

    if  t le 0.015072 then R=0;

      else if  t gt 0.015072 then R=1;

    y1= alpha1 +beta1*R + er;

    output;

  end;

run;

%do i=1 %to 7;

proc surveyselect data=tes_&i  method = urs sampsize = 10 OUTHITS

     reps=1 seed=123410 out=test_&i;

run;

proc means data = test_&i sum;

where obs = 0;

var censored; 

ods output summary = summary_&i;

run;

%end;

data impute_t_&p;

set summary_1 -summary_&i;;

run;

%end;

%mend surv;

%surv(replicates=10);

Solution
‎11-08-2013 12:37 AM
Respected Advisor
Posts: 3,900

Re: For loops

You can define a macro within a macro but if you want to use the macro then you need to call it. So you would need to add %selecting; to your code.

You normally avoid to define a macro in a macro because in doing so the inner macro definition gets re-compiled for every call of the out macro. So what you would do if such a nesting is required is a construct like:

%macro inner;

   ....

%mend;

%macro outer;

     %inner;

%mend;

%outer;

Also don't forget that macro variables defined within a macro have per default a scope of local. So &i defined in macro %selecting is not available in the outer macro %surv. You need to use a %global i; in your inner macro to change this.

I also believe that at the end of a %do loop the value of &i is the upper boundary of the loop plus 1 - so "summary_&i;" would expect a data set "summary_8" - which doesn't exist.

I actually don't understand why you need macro %selecting at all. Can't you just have your %do loop as part of macro %surv?

Another option to collect data created iteratively would be:

proc append base=impute_t_&p data=summary_&i;

run;

You would have this proc append step inside your do loop. If you don't need to keep a table per iteration then you could also overwrite the summary_.. table in each operation and so using syntax like:

proc append base=impute_t_&p data=summary;

run;

Haven't really looked at the rest of the code. What you normally want to do is make your program work without a macro (so only for a single case) and only once this is working "macrotize" it.

Also: It's most of the times better to use by-group processing instead of calling a procedure multiple times with different data slices. So eventually you could combine the output from proc sureveyselect using proc append but then call proc means only once.

☑ This topic is solved.

Need further help from the community? Please ask a new question.

Discussion stats
  • 4 replies
  • 265 views
  • 3 likes
  • 2 in conversation