Reputation: 3
I am taking a class on SAS and have a project to do. I'm not looking for the exact answer of course (though that would be nice), but a strong push in the right direction would be really appreciated.
The problem is to write a macro that creates age groups from a person's age in years. The code that is given is:
data a ;
infile in1 ;
input name $ age ;
if 30 le age < 33 then agegrp = 30 ;
else if 33 le age < 36 then agegrp = 33 ;
else if 36 le age < 39 then agegrp = 36 ;
else if 39 le age < 42 then agegrp = 39 ;
else if 42 le age < 45 then agegrp = 42 ;
else if 45 le age < 48 then agegrp = 45 ;
else if 48 le age < 51 then agegrp = 48 ;
else if 51 le age < 54 then agegrp = 51 ;
else if 54 le age < 57 then agegrp = 54 ;
else if 57 le age then agegrp = 57 ;
My job is to write a SAS macro that generates these if-then/else statements. Here is what I have so far. I realize that this will not run, but I wanted to get something down to show you guys how far I'm able to get with this assignment.
options ls=78 formdlim=' ' ;
%MACRO CODEIT(start= , stop= , count= , old= , new= );
%let x=&start;
%let y=%eval(&start+&count);
if &start
%do x=&start+&count %to &stop %by &count ;
<= &old < &x then &new=&start ;
%let start=&x ;
else if &start
%end ;
<= &old then &new=&start ;
%MEND
data a ;
input age ;
datalines;
30 31 32 33 34 37
38 39 39 41 42 45
46 46 47 49 50 50
52 53 54 55 56 57
%CODEIT(start=30, stop=57, count=3, old=0, new=0);
I thank you so much for all of your help in advance.
Upvotes: 0
Views: 1112
Reputation: 63424
You have a few minor problems, but (given the specific requirement) generally have this down.
First off, the macro needs to be executed inside a data step. You have datalines, however, which mean this won't run properly - datalines must be the last part of the data step.
data a;
input age;
<%codeit call>
datalines;
<data>
;;;;
run;
Second, your %do
control is slightly wrong. You actually can do this two ways; you could in theory use %do
, but really you ought to use do
. I would also change how start/end work, but that's just personal preference (I would make start
not the lowest value but the lowest range starting point; and end
should be the highest range ending point, as that makes the most logical sense to me).
do _iter = &start to &stop by &count;
if _iter. le &old. lt _iter+&count. then &new. = &start.;
end;
if &old. lt &start. then &new.=&start.-&count.;
else if &old. ge &end then &new. = &old.+&count.;
That should be your macro.
Now, that said, there's no reason to use a macro for this; you could do all of that work in a data step. If this is a macro class, then you can make roughly the same code in %do
; you still want to wrap the entire if
in %do
(you would use &_iter.
or whatever you use for your iteration variable).
In a real life scenario, you could either have the do loop I posted without macro variables (just hardcoded), or you could more effectively use a select
statement; or, even better, use a format (proc format
) to implement the recode. Formats really are the best option as this is exactly what they're made for, and they can be done without needing a new datastep.
Upvotes: 1