Hi all,
I want to do a variable group by a macro variable, however, the values are wrong.
The macro I created is displayed below:
%macro refigrp(refi,refigrp);
if &refi.<=0 then &refigrp.='a.<=0';
else if 0<&refi.<=0.1 then &refigrp.="b.0<-0.1";
else if 0.1<&refi.<=0.2 then &refigrp.="c.0.1<-0.2";
else if 0.2<&refi.<=0.3 then &refigrp.="d.0.2<-0.3";
else if 0.3< &refi.<=0.4 then &refigrp.='e.0.3<-0.4';
else if 0.4<&refi.<=0.5 then &refigrp.='f.0.4<-0.5';
else if 0.5<&refi.<=0.6 then &refigrp.='g.0.5<-0.6';
else if 0.6<&refi.<=0.7 then &refigrp.='h.0.6<-0.7';
else if 0.7<&refi.<=0.8 then &refigrp.='i.0.7<-0.8';
else if 0.8<&refi.<=0.9 then &refigrp.='j.0.8<-0.9';
else if 0.9<&refi.<=1.0 then &refigrp.='k.0.9<-1.0';
else if 1.0<&refi.<=1.1 then &refigrp.='l.1.0<-1.1';
else if 1.1<&refi.<=1.2 then &refigrp.='m.1.1<-1.2';
else if 1.2<&refi.<=1.3 then &refigrp.='n.1.2<-1.3';
else if 1.3<&refi.<=1.4 then &refigrp.='o.1.3<-1.4';
else if 1.4<&refi.<=1.5 then &refigrp.='p.1.4<-1.5';
else if 1.5<&refi.<=1.6 then &refigrp.='q.1.5<-1.6';
else if 1.6<&refi.<=2.0 then &refigrp.='r.1.6<-2.0';
else &refigrp.='s.>2.0';
%mend;
what I wanted like this:
refiincentivedifInc100bps | refigrp100 should like this |
0.321499985 | 0.3<-0.4 |
0.355833238 | 0.3<-0.4 |
0.227666729 | 0.2<-0.3 |
0.465999978 | 0.4<-0.5 |
0.389166722 | 0.3<-0.4 |
0.477333317 | 0.4<-0.5 |
0.939166651 | 0.9<-1.0 |
0.971999997 | 0.9<-1.0 |
0.537166653 | 0.5<-0.6 |
However, what I got is shown below:
refiincentivedifInc100bps | refigrp100 |
0.321499985 | e.0.3 |
0.355833238 | e.0.3 |
0.227666729 | d.0.2 |
0.465999978 | f.0.4 |
0.389166722 | e.0.3 |
0.477333317 | f.0.4 |
0.939166651 | k.0.9 |
0.971999997 | k.0.9 |
0.537166653 | g.0.5 |
I tried using %SYSEVALF in the above macro, e.g. if 0.1<%SYSEVALF(&refi.)<0.2 then... it does not work,either.
Anyone knows how to fix the code that it works?
Your macro looks fine, but there is nothing in it to define the length of the new variable. Either add a length statement in the code the macro generates or just define the new variable before you call the macro.
data want ;
set have ;
length refigrp100 $10 ;
%refigrp(refiincentivedifInc100bps,refigrp100)
run;
Just a quick comment that this is better accomplished with a format rather than a macro.
If you just want to apply format then you don't even need the letters since it will sort correctly.
Also your want doesn't show the letters that are clearly in your code (a/b/c).
You could also dynamically use a formula for this:
data have;
input num;
range = catx("->", round(floor(num*10)/10, 0.1), round(ceil(num*10)/10, 0.1));
cards;
0.321499985
0.355833238
0.227666729
0.465999978
0.389166722
0.477333317
0.939166651
0.971999997
0.537166653
;
run;
The task is much better handled with a user-defined format than with a long if-then-else-if chain.
Keep in mind that comparison operations are the most CPU-consuming operations (on machine code level) and can therefore cause unnecessary bad performance.
In your specific case, the length of the variable named by &refigrp is defined when the data step compiler encounters the first assignment oepration ('a.<=0') and therefore assigns it a length of 5, which is not sufficent to hold the longer values that appear later in the code.
That is why you need an explicit length statement.
It is always good practice to specify length for a newly created character variable, unless you do that implicitly by assigning a format or inputting with a format.
Thanks, adding length statement in the data before calling the macro works.
I have to define variable group in this way, as those categorical variables will be predicators in a model. Formatting cannot work.
You can use the format in a put statement and avoid the if-then-else-if chain, instead having a single assignment statement.
Are you ready for the spotlight? We're accepting content ideas for SAS Innovate 2025 to be held May 6-9 in Orlando, FL. The call is open until September 25. Read more here about why you should contribute and what is in it for you!
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.