BookmarkSubscribeRSS Feed
🔒 This topic is solved and locked. Need further help from the community? Please sign in and ask a new question.
chrisengel
Obsidian | Level 7

Hello SAS community,

 

I've built some code in data steps that I am now going to have to repeat on many other data sources, so I'm changing the code over to %macro in order to easily apply it many times. However I've run into an issue.

 

First i will show the original code snippet, then I will show a toy example I am playing with to find out exactly what is causing the problem:

 

%do j=1 %to &d;
  %if %substr(array{j},1,5) in ("str1", "str2", "str3") %then %do;
      if var1 > 3 then var2="no";
  %end;
%end;

THis produces error4:

"Macro function %substr has too many arguments. The excess arguments will be ignored.

A character operand was found in the %EVAL function or %IF condition where a number operand is required. The condition was: j}

Argument 2 to macro function %substr is not a number.

Operand missing for IN operator to argument to %EVAL function"

 

So one of the first things I realised when converting code to macros is that the %dos and %ifs need to have percent prefix to avoid issues, then i found out that substr() is not valid in macros, so you ahve to use either %substr or %sysfunc(substr()). Then I learned that "IN" is also not valid, unless you include options to allow it before code. 

 

GIven these lessons, I have tried to now use a toy example just to test out the general functionality of declaring array elements and checking substr of the value of them using "in" operand. Here's my test code:

 

data test;
input id $ answer1 $ answer2 $;
datalines;
1 yes maybe 
2 no maybe
3 maybe maybe
;
run;

options minoperator mindelimiter=',';
%macro substringtest();

data test2;
set test;
array answer{2};

%do i=1 %to 2;
%if %substr(answer{i},1,1) in ("y", "n") %then %do;
certain&i=1;
%end;
%else %do;
certain&i=0;
%end;
%end;

run;
%mend;

%substringtest;

When running this, I get no mlogic issues, but the values for obs 1 and 2 "certain1" should be "1", but they are all 0 for certain1 and certain2.

 

I'm now a little confused regarding a few things

 

1) Why is the substr argument workign in test code but no the real code.

2) Why isn't the test code producing proper variable outputs reflecting correct logic.

3) Is there some easier way to get around using do blocks? I have other macros I converted to which uses substr and arrays and in just fine, but because i have further conditions after, i have some parts that are in "do" blocks. Maybe there's a workaround to just not do this?

 

Thanks ahead of time.

1 ACCEPTED SOLUTION

Accepted Solutions
Astounding
PROC Star

If you're using DATA step code, arrays might look like this:

 

array answer {2};

array certain {2};

do i=1 to dim(answer);

   if substr(answer{i}, 1, 1) in ('n', 'y') then certain{i}=1;

   else certain{i}=0;

end;

 

Even that could likely be simplified by removing SUBSTR entirely.  It all depends on what might be found in the ANSWER variables.  If macro language were to be inserted into this program, it would only be to define the array dimensions:  {&d}

 

If you to use macro language instead of arrays, it might look like this:

 

%do i=1 %to 2;

   if substr(answer&i 1, 1) in ('n', 'y') then certain&i=1;

   else certain&i=0;

%end;

 

Macro language is not processing your data.  It is generating the proper SAS statements needed to process your data once the DATA step begins to execute.

View solution in original post

3 REPLIES 3
Reeza
Super User

There's nothing in your loop that requires a macro. If you're in a data step use a regular do loop. 

 

Use a macro do loop to repeat procedures. 

 

Your code below would change to declare a certain array as well. 

 

If this doesn't reflect your actual situation then please make an example that's relevant. 

 

1. macro comparisons don't include quotes. in y, n http://support.sas.com/kb/35/591.html

2. Your evaluation is never hitting true. Add %put to,each %if condition so you can trace your logic. 

3. See stuff before this. 

 

Astounding
PROC Star

If you're using DATA step code, arrays might look like this:

 

array answer {2};

array certain {2};

do i=1 to dim(answer);

   if substr(answer{i}, 1, 1) in ('n', 'y') then certain{i}=1;

   else certain{i}=0;

end;

 

Even that could likely be simplified by removing SUBSTR entirely.  It all depends on what might be found in the ANSWER variables.  If macro language were to be inserted into this program, it would only be to define the array dimensions:  {&d}

 

If you to use macro language instead of arrays, it might look like this:

 

%do i=1 %to 2;

   if substr(answer&i 1, 1) in ('n', 'y') then certain&i=1;

   else certain&i=0;

%end;

 

Macro language is not processing your data.  It is generating the proper SAS statements needed to process your data once the DATA step begins to execute.

ballardw
Super User

If you have many variables in multiple datasets that need similar RECODING then possibly you want a custom INFORMAT.

Please see the example below:

proc format library=work;
invalue YNM (upcase)
'YES','NO'=1
other = 0;
run;

data example;
   input x $;
datalines;
yes
Yes
No
no
maybe
.
never
;
run;

data want;
   set example;
   varx = input(x,YNM.);
run;

Note that if this were my data I would be very tempted to read the values initially with the appropriate informat instead recoding them later.

 

Informats and Formats can sometimes remove a lot of IF/THEN/ELSE code involving non-overlapping values for single variables.

Also note the inclusion of "never" in the data example. Your code using substr would set this to 1 but the original value was not "no".

sas-innovate-2024.png

Join us for SAS Innovate April 16-19 at the Aria in Las Vegas. Bring the team and save big with our group pricing for a limited time only.

Pre-conference courses and tutorials are filling up fast and are always a sellout. Register today to reserve your seat.

 

Register now!

How to Concatenate Values

Learn how use the CAT functions in SAS to join values from multiple variables into a single value.

Find more tutorials on the SAS Users YouTube channel.

Click image to register for webinarClick image to register for webinar

Classroom Training Available!

Select SAS Training centers are offering in-person courses. View upcoming courses for:

View all other training opportunities.

Discussion stats
  • 3 replies
  • 1213 views
  • 1 like
  • 4 in conversation