Search code examples
if-statementsassas-macro

if statement conditions are embedded in a column


I have a SAS table that has the if condition embedded in the condition1 column of that table. To be more explicit, I created a test dataset:

data test;
infile datalines delimiter=','; 
input x1 x2 flag $ condition1 $ value_cond1_true $ value_cond1_false $ ;
datalines;                      
1,5, ,x1>x2,A,B
6,5, ,x2>x1,D,A
3,2, , ,C,D
;
run;

I am wondering if it possible to create a code that can directly output in the SAS code the if statement instead of creating a single macro-variable for each observation (&cond1_1, &cond1_2, ... &cond1_n).

Here is what I would want to do (I know it is not possible to use call symput in that case):

data final;
set test;
/* For each observation */
do i=1 to _n_;
/* Creating macro-variables for the if condition */
call symput("cond1",CONDITION1);
call symput("value_cond1_true",VALUE_COND1_TRUE);
call symput("value_cond1_false",VALUE_COND1_FALSE);
/* If the cond1 macro-variable is not empty then do */
if %sysevalf(%superq(cond1)=, boolean) = 0 then do;
    if &cond1. then flag = &value_cond1_true.;
        else flag = &value_cond1_false.;
    end;
/* If the cond1 macro-variable is empty then */
else flag = "X";
end;
run;

Solution

  • Data can not modify the statements of a running DATA Step.

    There is no 'dynamic expression resolver' that is part of data step.

    There are some options though

    • Use the data to write source code
      • A different conditional has to be performed for each row (n)
    • Use resolve() to dynamically evaluate an expression in the macro system.
      • The values of the variables have to be replaced into the conditional for each row (n)

    Write a program

    
    filename evals temp;
    
    data _null_;
      file evals;
      set test;
    
      length statement $256;
    
      put 'if _n_ = ' _n_ ' then do;';
    
      if missing(condition1) then 
        statement = 'flag="X";'; /* 'call missing(flag);'; */
      else
        statement = 'flag = ifc(' 
        || trim(condition1) || ',' 
        || quote(trim(value_cond1_true )) || ','
        || quote(trim(value_cond1_false ))
        || ');';
    
      put statement;
      put 'end;';
    run;
    
    options source2;
    
    data want;
      set test;
      length flag $8;
      %include evals;
      keep x1 x2 flag;
    run;
    
    filename evals;
    

    RESOLVE function

    data want;
      set test;
    
      length flag $8 cond expr $256;
    
      cond = condition1;
      cond = transtrn(cond,'x1',cats(x1));
      cond = transtrn(cond,'x2',cats(x2));
    
      expr = 'ifc(' || trim(cond) || ',' || 
               trim(value_cond1_true) || ',' || 
               trim(value_cond1_false) ||
             ')';
    
      if not missing (condition1) then 
        flag = resolve ('%sysfunc(' || trim(expr) || ')');
      else
        flag = "X";
    
      keep x1 x2 flag;
    run;