Reputation: 1537
%let Q1 = 0.2;
%let Q2 = 0.3;
%let Q3 = 0.4;
%let Q4 = 0.5;
a1
has a column named Qtr
which indicates its quarter this year. Original code is
data a2;
set a1;
if Qtr = 1 then QtrE = &Q1;
if Qtr = 2 then QtrE = &Q2;
if Qtr = 3 then QtrE = &Q3;
if Qtr = 4 then QtrE = &Q4;
run;
data a3;
set a2;
calculated = base * QtrE;
run;
I think the original one is very clumsy. If the effect is by month not by quarter, then I have to write more code just to do the simple calculation. So I wrote the following code. But it didn't work. It seems the macro variable Qtr
did't change row by row.
data a3;
set a1;
call symput('Qtr',cat('Q',Qtr));
calculated = base * &&&Qtr;
run;
Upvotes: 1
Views: 83
Reputation: 8513
I think DomPazz's recommendation of avoiding macros altogether is the best way to go. If for some reason you can't do this, one more option is also to use the symget()
function:
data a3;
set a1;
call symput('Qtr',cat('Q',Qtr));
calculated = base * input(symget(symget('qtr')),best.);
run;
According to the documentation, symget...
Returns the value of a macro variable during DATA step execution.
Upvotes: 1
Reputation: 63424
RESOLVE should get you what you're looking for in this case. I don't disagree with Dom that realistically you should create a lookup table (a format is best IMO here), but the specific question can be solved.
This is only true because the value of the macro variable is being used as a value in the code - ie, it doesn't really matter in the compilation step that it's not yet defined. Macro variables that are used to define variable names on the left side of an equal sign, or as a function, or other things like that cannot be used in this manner.
%let Q1 = 0.2;
%let Q2 = 0.3;
%let Q3 = 0.4;
%let Q4 = 0.5;
data a1;
do q=1 to 4;
output;
end;
run;
data a2;
set a1;
qtre=resolve(cats('&Q',q));
run;
Upvotes: 1
Reputation: 12465
You should read the documentation on how symput() works in relation to the macro compiler and the data step compiler. http://support.sas.com/documentation/cdl/en/mcrolref/68140/HTML/default/viewer.htm#p09y28i2d1kn8qn1p1icxchz37p3.htm
Short story is that your code doesn't work because the macro compiler resolves &&&Qtr and then passes that to the Data Step.
Macros write SAS code for you. SAS code is then compiled and run.
Think about it this way, that Data Step is compiled into a foreach loop.
foreach(record in a1):
call symput(...);
record.calculated = record.base * <value of &qtr>;
But the value of &qtr is resolved BEFORE the code above is written.
The creation of a lookup table is probably the best way to go. Left join that on the table with your values. There are numerous ways to do a left join in SAS.
Upvotes: 2