简体   繁体   中英

Creating Intervals using SAS Macro

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.

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM