BookmarkSubscribeRSS Feed
rdwest
Calcite | Level 5
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;
7 REPLIES 7
chang_y_chung_hotmail_com
Obsidian | Level 7
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.


   */


 

rdwest
Calcite | Level 5
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 -
art297
Opal | Level 21
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
art297
Opal | Level 21
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
rdwest
Calcite | Level 5
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!
Cynthia_sas
SAS Super FREQ
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
Peter_C
Rhodochrosite | Level 12
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

sas-innovate-2024.png

Join us for SAS Innovate April 16-19 at the Aria in Las Vegas. Bring the team and save big with our group pricing for a limited time only.

Pre-conference courses and tutorials are filling up fast and are always a sellout. Register today to reserve your seat.

 

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
  • 7 replies
  • 1085 views
  • 0 likes
  • 5 in conversation