1
votes

I have a data having field Income , Age and Cond where A and B are numeric and Cond contains conditions (string) like "If Income>=10000", "If Age<=35" etc. I want to use field Cond for filtering of the data. I am using call symput to create runtime macro variable inside data step bt unable to use it as filtering criterion.

data T2;
    set T1;
    CALL SYMPUT("Condition", Cond);
    &Condition.; /*this is the line which is not working*/
run;
2
Please show sample data and desired output. This will help explain how you want to handle ‘different conditions for each row ‘Quentin

2 Answers

1
votes

You are mixing scopes.

A running data step can not change it's running source code, so you can't have a data step set a macro variables value and then expect the data set to use the resolution of the macro variable as source code.

You can use a variety of techniques to evaluate an expression.

CALL EXECUTE

You can use call EXECUTE to %EVAL an expression in the macro environment while a DATA step is running. The result can be retrieved with SYMGET

Example of idea

  %let x = 0;

  data _null_;

    length expression $1000;

    expression = '%let x = %eval(10 + 20)';
    call execute (expression);

    x = symget('x');
    put x=;
  run;

Using the idea

  data want;
    set have;

    condition = tranwrd(condition, 'age', cats(age));
    condition = tranwrd(condition, 'income', cats(income));

    call execute (cats('%let result = %eval(', condition, ')'));

    result = symget('result');

    * subsetting if based on dynamic evaluation of conditional expression;
    if result;
  run;

Other

Other ways to execute dynamic code is through functions RESOLVE or DOSUBL

0
votes

Good day,

I assume you have only a single condition in the table? (Same reason every row.) Unless, you need to select the proper reason via other reasons. This takes the reason in the last row.

Firtst lets generate some dummmy data.

    data T1; 
        infile datalines delimiter=','; 
        input cond $21. Income  age  ;  
        cards;
        "If Income>=10000" , 1000 , 10
        "If Income>=10000" , 10000 , 100 
        "If Income>=10000" , 100000 , 1000
    ;run;

What we do here is create Global variable &condition into which we put the last value of Cond-column. You can also use proc sql to easily select desired string into the variable. See more on proc sql Into here

    data _NULL_;
        set T1;
        CALL SYMPUT("Condition", Cond);
    run;

Here we begin with set T1 and apply the String &condition, which contains the rule. I needed to remove the quotes from the command in order to get SAS to perform the function. It is a bit unconventional to apply command this way but works.

    data T2; 
        set T1; 
        %qsysfunc(dequote(&Condition.)); 
    run;

EDIT: Based on further elaboration the following has been tested to work. One feeds the conditions to macro loop, which selects the condition. If there are dupilates, I suggest you split conditions and data to different sets.

%macro Create_subset(Row);
    data _NULL_;
        set T1(firstobs=&row obs=&row.);
            CALL SYMPUT("Condition", Cond);
    run;

    data Subset_&row.; 
        set T1; 
     %qsysfunc(dequote(&Condition.)); 
     applied_cond = &Condition.;
    run;
%mend Create_subset;
data _NULL_;
    set T1; 
    call execute('%nrstr(%Create_subset('||strip(_N_)|| '))');
run;