DATA Step, Macro, Functions and more

Simple do loop question.

Reply
Occasional Contributor
Posts: 10

Simple do loop question.

Hello,

I am trying to clean up quite a bit of redundant code with macros using do loops. However, I think I'm missing some insight about the way macros replace variables. For example, this long form works fine:

Data y; set x;
dep_perf_0 = 0; dep_perf_1 = 0; dep_perf_2 = 0; dep_perf_3 = 0; dep_perf_4 = 0; dep_perf_5 = 0; dep_perf_6 = 0;
if seat_class_id = 0 then dep_perf_0 = sum_departures_performed;
if seat_class_id = 1 then dep_perf_1 = sum_departures_performed;
if seat_class_id = 2 then dep_perf_2 = sum_departures_performed;
if seat_class_id = 3 then dep_perf_3 = sum_departures_performed;
if seat_class_id = 4 then dep_perf_4 = sum_departures_performed;
if seat_class_id = 5 then dep_perf_5 = sum_departures_performed;
if seat_class_id = 6 then dep_perf_6 = sum_departures_performed;
run;


I've tried to translate this into a macro with this code:


%macro a;
data y; set x;
%do i = 0 %to 6;
dep_perf_&i = 0;
%if seat_class_id = &i %then %let dep_perf_&i = sum_departures_performed;
%end;
run;
%mend a;

%a;



This creates all the variables dep_perf_&i, and inserts the value of 0 in each, but does not replace the zero with the appropriate value when the "if" condition is true. I thought perhaps SAS was not interpreting "&i" as a number, but even when I insert a numerical value for seat_class_id, no replacement occurs:


%macro a;
data y; set x;
%do i = 0 %to 6;
dep_perf_&i = 0;
%if seat_class_id = 0 %then %let dep_perf_&i = sum_departures_performed;
%end;
run;
%mend a;

%a;
Regular Contributor
Posts: 241

Re: Simple do loop question.

Here is a simpler way with an array.



   /* test data */


   data x;


     do seat_class_id = 0 to 6;


       sum_departures_performed = seat_class_id * 10;


       output;


     end;


   run;


 


   /* wall-paper code */


   data rdwest; 


     set x;


     dep_perf_0 = 0; dep_perf_1 = 0; dep_perf_2 = 0


     dep_perf_3 = 0; dep_perf_4 = 0; dep_perf_5 = 0


     dep_perf_6 = 0


     if seat_class_id = 0 then dep_perf_0 = sum_departures_performed;


     if seat_class_id = 1 then dep_perf_1 = sum_departures_performed;


     if seat_class_id = 2 then dep_perf_2 = sum_departures_performed;


     if seat_class_id = 3 then dep_perf_3 = sum_departures_performed;


     if seat_class_id = 4 then dep_perf_4 = sum_departures_performed;


     if seat_class_id = 5 then dep_perf_5 = sum_departures_performed;


     if seat_class_id = 6 then dep_perf_6 = sum_departures_performed;


   run;


 


   /* array code */


   data array;


     set x;


     array dp(0:6) dep_perf_0 - dep_perf_6;


     drop i;


     do i = 0 to 6; dp(i) = 0end;


     dp(seat_class_id) = sum_departures_performed;


   run;


 


   /* check */


   proc compare base=rdwest compare=array;


   run;


   /* on lst - in part


     NOTE: No unequal values were found. All values compared are exactly equal.


   */


 

Occasional Contributor
Posts: 10

Re: Simple do loop question.

Thank you! That works quite well -- I appreciate the help.

You are correct that I'm not ready for macros if I can't properly distinguish when they are necessary -- but I'll assume all of the manipulations I need to do can be undertaken using arrays until something indicates otherwise......

Thanks again -
PROC Star
Posts: 7,363

Re: Simple do loop question.

I'm glad to hear that Chang's code gets you where you need to be. However, to say "You are not yet ready for SAS Macro language" doesn't ring right with me.

You were o-so-close! One will NEVER be ready for SAS Macro language unless they try. Yes, by definition, that will probably mean some failures. But the eventual rewards will far make up for the aggravation.

In the first part of your code, is the following all you were trying to do:


/* test data */
data x;
do seat_class_id = 0 to 6;
sum_departures_performed = seat_class_id * 10;
output;
end;
run;

%macro a;
data y;
set x;
%do i = 0 %to 6;
dep_perf_&i = 0;
if seat_class_id = &i then dep_perf_&i = sum_departures_performed;
%end;
run;
%mend a;

%a

If so, just compare that with what you had tried.

Art
PROC Star
Posts: 7,363

Re: Simple do loop question.

I'm glad to hear that Chang's code gets you where you need to be. However, to say "You are not yet ready for SAS Macro language" doesn't ring right with me.

You were o-so-close! One will NEVER be ready for SAS Macro language unless they try. Yes, by definition, that will probably mean some failures. But the eventual rewards will far make up for the aggravation.

In the first part of your code, is the following all you were trying to do:


/* test data */
data x;
do seat_class_id = 0 to 6;
sum_departures_performed = seat_class_id * 10;
output;
end;
run;

%macro a;
data y;
set x;
%do i = 0 %to 6;
dep_perf_&i = 0;
if seat_class_id = &i then dep_perf_&i = sum_departures_performed;
%end;
run;
%mend a;

%a

If so, just compare that with what you had tried.

Art
Occasional Contributor
Posts: 10

Re: Simple do loop question.

Yes! That accomplishes what I had intended. Now I understand where I was mistaken: I wasn't creating a new macro variable, so there was no need to use the "%let" command. And furthermore, I needed a standard if-then statement, not a macro statement. I'm not sure that I understand how to recognize when to use if-then versus %if - %then : the only description I've found of the difference is this: "%IF statements can contain actions that standard IF statements can't contain, such as complete DATA or PROC steps and even other macro statements."

Thanks again - that was very helpful!
SAS Super FREQ
Posts: 8,743

Re: Simple do loop question.

Hi:
Here are some really good papers on SAS Macro processing:
http://www2.sas.com/proceedings/sugi28/056-28.pdf
http://www2.sas.com/proceedings/sugi29/128-29.pdf (this paper has a good discussion/examples on IF versus %IF)
http://www2.sas.com/proceedings/sugi27/p067-27.pdf (the last sentence in this paper is: "Often in DATA step programming, arrays provide a better answer than macro.")
http://analytics.ncsu.edu/sesug/2006/HW02_06.PDF

For me, the key to understand when to use %IF versus DATA step IF hinges on really understanding that the Macro facility only acts like a big typewriter to write entire programs, lines of codes or parts of statements. Just remember that by the time your code gets to the compiler there are NO macro variable references or triggers (&macvar or %macpgm) left in the program (if you have not made any errors). So it is sometimes easier to start with a working .SAS program that produces the results you want and then work your way into macro processing by figuring out how you can use macro variable references and/or macro programs to generate the working code...and then to generate variations of the working code.

You also need to REALLY understand the difference between macro program compile, macro program execution phases and do NOT confuse them with DATA step compile and DATA step execution phases.

cynthia
Valued Guide
Posts: 2,175

Re: Simple do loop question.

Hi rdwest
since your "wall paper code" (as described by chang_y_chung@hotmail.com) are mutually-exclusive IF tests, only one will be true.
That is the only assignment code you need
So:[pre] seat_class_id[/pre]indicates which of the [pre] dep_perf_[/pre]variables should have the vaue in[pre] sum_departures_performed[/pre]So that just needs code like[pre]array dep_perf_(0:6) dep_perf_0 - dep_perf_6 ;
if 0 LE seat_class_id LE 6 then
dep_perf_( seat_class_id ) = sum_departures_performed ;[/pre]No macros at all.
Macros or macro variables might help if the 0 and 6 are more dynamic.

peterC
Ask a Question
Discussion stats
  • 7 replies
  • 192 views
  • 0 likes
  • 5 in conversation