1

I'm having trouble getting If/Then statements to work correctly with my macro variables inside a datastep. I'm writing a macro to handle two different cases: calculating stat tests with no transformation, and then calculating stat tests after a natural log transformation. If my data fails the test of normality, I log transform and test again. If it passes, I set my global flag, log_flag, to 1. I then want to test the status of this flag in data steps in order to correctly handle the transformed (or not) variables. I've tried variations of the following:

Data want;
set have;
if symget("log_flag")=1 then do;
if &log_flag. = 1 then do;
if resolve("log_flag")=1 then do;
test=symget("log_flag");
  if test=1 then do;
end

No matter what I try, the if/then statement is essentially ignored and all code following it is processed as if the if/then were true, even when it is false. I know that the log_flag is being correctly assigned a value of zero because the %if %then statements work and execute correctly in open code. I'm just having trouble getting it to resolve correctly inside a datastep.

Please let me know if there is any other information you need to help me figure this out. Thanks guys!

Kevin.C
  • 309
  • 1
  • 2
  • 10
  • look into this paper https://www.lexjansen.com/pnwsug/1998/PNWSUG98026.pdf – Kiran Oct 02 '18 at 13:17
  • That's a really good reference, thanks, but I'm still having the problem where my logical comparison is not being evaluated. I can load the macro variables in, and when I assign the `test` variable the macro variable value, it gets assigned correctly (0 in this case). When I try to do a logical comparison on this value, it doesn't work. No errors are produced, but it basically ignores the comparison, or acts like it's true when it's actually false. Does this make sense? – Kevin.C Oct 02 '18 at 13:35
  • below code works.%let a =1; data class; set sashelp.class; if symget("a") = "1" then do; b=20; c=5; end; run; – Kiran Oct 02 '18 at 14:20
  • You could be mixing macro symbol assignment and evaluation scopes. How do you set `log_flag` ? How do you run your Proc steps ? Does the log show the proper values if you code a `%put _global_;` statement prior to the DATA step ? Show your code where `%if %then` are used in open code and why you think it is correct. What version of SAS are you running ? – Richard Oct 02 '18 at 14:31
  • I set `log_flag` using `%let` statements based on the results logic test of the p-values from proc univariate. I have a screen shot of symbolgen telling me that `%if condition &log_flag.=1 is FALSE`. That tells me that the logic test in open code works, but for some reason it is not working during the data step. When I use `%put` it shows me that `log_flag` evaluates to 0 as it should. I'm using 9.4. I never try to reassign `log_flag` in a datastep, only in open code as a result of logic tests. – Kevin.C Oct 02 '18 at 14:41

2 Answers2

2

The issue you have identified in the comments is that you do not want to generate the SAS code at all. That is what the macro language processor is for. So use %IF to conditionally generate the code.

So if you only want to create the variable newvar when the macro variable log_flag is one then you could code it this way.

data want ;
  set have ;
%if &log_flag. = 1 %then %do;
  newvar= x*y ;
%end;
run;

So when &log_flag. = 1 you run this code:

data want ;
  set have ;
  newvar= x*y ;
run;

And when it isn't you run this code:

data want ;
  set have ;
run;

Starting with SAS 9.4 M5 release you can use this in open code, otherwise place it inside a macro definition and execute the macro.

Tom
  • 47,574
  • 2
  • 16
  • 29
  • This is absolutely correct. I had forgotten that if/then statements still generate the variables contained within unless the "%" is included. – Kevin.C Nov 20 '18 at 14:22
0
  • SYMGET() will return a character variable.
  • RESOLVE() will return a character variable, but it needs the & in the parameter.
  • &log_flag will resolve as numeric

You need to treat them correctly depending on your reference method.

Here's an example of testing each one independently and then you can test them together via nesting if desired.

%let log_flag=1;
Data want;
set sashelp.class;
if symget("log_flag")='1' then do;
  put "Test #1 is True";
end;

if &log_flag. = 1 then do;
  put "Test #2 is True";
end;


if resolve("&log_flag")="1" then do;
  put "Test #3 is True";
end;

test=symget("log_flag");
if test='1' then do;
  put "Test #4 is True";
end;

run;
Reeza
  • 20,510
  • 4
  • 21
  • 38
  • Reeza gave me the solution in a different thread. I need to use `%if &log_flag =1 %then %do` because using the `%ifs` prevent the step from compiling if the logical comparison is false. Hopefully this helps someone else! – Kevin.C Oct 02 '18 at 15:34