Warm tip: This article is reproduced from serverfault.com, please click

if statement conditions are embedded in a column

发布于 2020-12-02 12:43:24

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;
Questioner
Kermit
Viewed
0
Richard 2020-12-03 01:33:45

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;