Lovnlust
Lovnlust

Reputation: 1537

rewrite these code using macro variable

%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

Answers (3)

Robert Penridge
Robert Penridge

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

Joe
Joe

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

DomPazz
DomPazz

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

Related Questions