Search code examples
stringsassas-macro

SAS macro to loop through dataset variables and perform string matching


I need to search through the 15 variables of a dataset for a specific substring (the word "None"). When I use the code below for just one variable, I can get the results I want. However, when I try to use a Macro to loop through all 15 variables, the code does not detect the word None - although there are no errors in the log. Here is some sample data:

ID Var_1 Var_2 Var_3
11 None(0%) Nearly all(100%) None(0%)
12 Nearly all(100%) None(0%) None(0%)
13 None(0%) Some (50%) Nearly all(100%)

SAS Code without macros (for just one variable in the dataset):

data countvar;
set indata;
length word $ 25;
searchstr = var_1;
** Count occurrences of substring None
None_flag=0; 
   do i=1 to countw(searchstr); 
       word=scan(searchstr,i);
       if findw("None",strip(word),'i')>=1 then do;
           None_flag=1; 
       end; 
   end; 
run; 

Code when I use a macro to iterate through a list of variables in the dataset:

%macro loopit(list);
    data countvar1;
    set indata;
    %do i = 1 %to %sysfunc(countw(&list.));
        %let word  = %scan(&list., &i.);
        None_flag=0;
    
        %if %sysfunc(findw(None,strip(&word),ii))>=1 %then %do;
            None_flag=1;
        %end;
    %end;
    run;
%mend loopit;
%let list = Var_1 Var_2 Var_3 Var_4;
%loopit(list=&list)

The Macro code does not throw any errors - however, the variable None_flag in the output dataset is always zero. What is going wrong, please advice. Thanks.


Solution

  • Avoid macros and use an array. The issue with your macro 'solution' is that the none_flag can get reset to =0 and you are mixing scopes.

    data have;
    infile datalines dlm=',';
    length id 8 var_1-var_3 $20;
    input ID    Var_1   Var_2 var_3;
    datalines;
    11, None(0%),   Nearly all(100%),   None(0%)
    12, Nearly all(100%),   None(0%),   None(0%)
    13, None(0%),   Some (50%), Nearly all(100%)
    ;
    
    data want;
      set have;
      array vars var_1-var_3;
      do _i_ = 1 to dim(vars) while(not none_flag);
        none_flag = findw(vars,'none',,'ip');
      end;
    run;