Hi, I am learning to work with %IF %THEN in macros and neither of my below codes are working. Could you please help me understand what is going here?
data cars3;
set cars;
%macro tr (M=);
%if &M <30000 %then %do;
profitlabel= "greater than 30000";
%end;
%else %if &M>30000 %then %do;
profitlabel = "Less than 30000";
%end;
%mend;
%tr (M=msrp);
run;
/* Above code did not work---all values are populated as "Less than 30000"*/
/* Below code did not work---profitlabel is not created at all*/
data cars4;
set cars;
profit = msrp-invoice;
%macro msrp (T=, M=);
%if &T = "&M" %then %do;
if profit>3000 then profitlabel= "greater than 3000";
else profitlabel = "Less than 3000";
%end;
%mend;
%msrp (T=Make,M=Acura);
run;
Do not place macro definitions into the middle of a data step. The macro processor will process the macro statements and generate text that is passed to SAS to evaluate. So the macro definition will be compiled (and your call to it will run) BEFORE that data step is compiled and so before the data step can start running. Putting the macro definition into the middle of the data step will just confuse you.
You passed the macro the string msrp which you then compared to 30000. The letter m comes after the digit 3 so the macro always generates this statement.
profitlabel= "greater than 30000";
If you want to test the value of the variable MSRP you need your macro to generate an actual IF statement.
So if you run this program:
%macro tr (M=);
if &M <30000 then do;
profitlabel= "greater than 30000";
end;
else if &M>30000 %then do;
profitlabel = "Less than 30000";
end;
%mend;
data cars3;
set cars;
%tr (M=msrp);
run;
It is the same as running this data step without the macro.
data cars3;
set cars;
if msrp <30000 then do;
profitlabel= "greater than 30000";
end;
else if msrp>30000 %then do;
profitlabel = "Less than 30000";
end;
run;
Since the macro is resolved when code text is fetched for interpretation/compilation, it NEVER has access to the values of data step variables.
This macro
%macro tr (M=);
%if &M <30000 %then %do;
profitlabel= "greater than 30000";
%end;
%else %if &M>30000 %then %do;
profitlabel = "Less than 30000";
%end;
%mend;
%tr (M=msrp);
resolves macro variable &m to the text(!) msrp, so the condition turns into
%if msrp <30000 %then %do;
Since letters come after numbers in the ASCII character table, this condition resolves to false, and the following code is not created.
But the next condition is true, so the code from it is sent to the data step compiler, which now gets this code:
data cars3;
set cars;
profitlabel = "Less than 30000";
run;
What you want for your first code is this:
%macro tr (M=);
if &M ge 30000
then profitlabel= "greater than 30000";
else profitlabel = "Less than 30000";
%mend;
data cars3;
set cars;
%tr (M=msrp);
run;
Similar issues happen with your second code.
A simple rule of thumb:
%IF controls which code is created for the interpreter/compiler, while IF controls which part of the code (branch) is executed.
Available on demand!
Missed SAS Innovate Las Vegas? Watch all the action for free! View the keynotes, general sessions and 22 breakouts on demand.
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.