BookmarkSubscribeRSS Feed
☑ This topic is solved. Need further help from the community? Please sign in and ask a new question.
ari2495
Obsidian | Level 7
%macro check;

data check_esp_2;
set Base;

		%do i=1 %to 57;
			if var(i)>var(i-1) then flag=1 else flag=0;
		%end;
run;
		%mend;
%check;

1 ACCEPTED SOLUTION

Accepted Solutions
PaigeMiller
Diamond | Level 26

From now on, please SHOW US the log when you get an error. And since this is a macro, use options mprint; before you run the macro and we need to see the ENTIRE log for this macro, not just the error messages.

 

This is one of your errors: %DO works on macro variables. DO works on data step variables. Since you want i to be a data step variable, use DO.

 

Maybe you have over-simplified the code for the purposes of asking a question, but macro is completely unnecessary here.

 

data check_esp_2;
    set Base;
    array var var1-var57; /* Or any list of 57 valid SAS variable names */
    do i=2 to 57;
        if var(i)>var(i-1) then flag=1; else flag=0;
    end;
run;

 

Even with my corrections above, this code will run without errors but probably doesn't do what you want. This code is most likely giving the wrong results, but you don't tell us what you do want.

 

Please, pay attention to this advice: The best way to get macros to work is to first write WORKING code without macros and without macro variables, for one or two iterations of your problem. Had you done that, you would see that your code needs the ARRAY statement. If you can't get code working properly without macros and without macros variables, it will never work properly with macros and with macro variables. Some people ignore this advice, which is not a good way to proceed.

--
Paige Miller

View solution in original post

3 REPLIES 3
PaigeMiller
Diamond | Level 26

From now on, please SHOW US the log when you get an error. And since this is a macro, use options mprint; before you run the macro and we need to see the ENTIRE log for this macro, not just the error messages.

 

This is one of your errors: %DO works on macro variables. DO works on data step variables. Since you want i to be a data step variable, use DO.

 

Maybe you have over-simplified the code for the purposes of asking a question, but macro is completely unnecessary here.

 

data check_esp_2;
    set Base;
    array var var1-var57; /* Or any list of 57 valid SAS variable names */
    do i=2 to 57;
        if var(i)>var(i-1) then flag=1; else flag=0;
    end;
run;

 

Even with my corrections above, this code will run without errors but probably doesn't do what you want. This code is most likely giving the wrong results, but you don't tell us what you do want.

 

Please, pay attention to this advice: The best way to get macros to work is to first write WORKING code without macros and without macro variables, for one or two iterations of your problem. Had you done that, you would see that your code needs the ARRAY statement. If you can't get code working properly without macros and without macros variables, it will never work properly with macros and with macro variables. Some people ignore this advice, which is not a good way to proceed.

--
Paige Miller
ari2495
Obsidian | Level 7

Thank you for being so helpful, i'm sorry for not being compliant to the community rules. I apologize

Tom
Super User Tom
Super User

The error is that it is generating invalid SAS code.  

 

Turn on the MPRINT option to see what code it is generating. 

 

Let's change the upper bound to 3 to make the number of statements it generates smaller.

MPRINT(CHECK):   data check_esp_2;
MPRINT(CHECK):   set Base;
NOTE: Line generated by the invoked macro "CHECK".
3       if var(i)>var(i-1) then flag=1 else flag=0;
           ---    ---                  ----
           71     71                   388
                                       202
MPRINT(CHECK):   if var(i)>var(i-1) then flag=1 else flag=0 ;
NOTE: Line generated by the invoked macro "CHECK".
5       if var(i)>var(i-1) then flag=1 else flag=0;
           ---    ---                  ----
           71     71                   388
                                       202
MPRINT(CHECK):   if var(i)>var(i-1) then flag=1 else flag=0 ;
NOTE: Line generated by the invoked macro "CHECK".
7       if var(i)>var(i-1) then flag=1 else flag=0;
           ---    ---                  ----
           71     71                   388
                                       202
MPRINT(CHECK):   if var(i)>var(i-1) then flag=1 else flag=0 ;
MPRINT(CHECK):   run;

ERROR 71-185: The VAR function call does not have enough arguments.

ERROR 388-185: Expecting an arithmetic operator.

ERROR 202-322: The option or parameter is not recognized and will be ignored.

NOTE: The SAS System stopped processing this step because of errors.
WARNING: The data set WORK.CHECK_ESP_2 may be incomplete.  When this step was
         stopped there were 0 observations and 2 variables.
WARNING: Data set WORK.CHECK_ESP_2 was not replaced because this step was
         stopped.
NOTE: DATA statement used (Total process time):
      real time           0.00 seconds
      cpu time            0.00 seconds

So your %DO loop is generating the exact same statement over and over.  And the statement has syntax errors.  One is that there is no semicolon ending the IF statement.  Another is that you are using the VAR() function wrong.  I suspect that you were trying to index into an array, but you did not include any ARRAY statement in the generated data step to define such an array.

 

One LOGIC error is you seem to have confused the macro variable I used in the %DO loop with some data step variable I that is not defined anywhere. 

 

Another LOGIC error is you have multiple IF/THEN/ELSE statements that are each setting the same variable to 1 or 0.  So only the result of the LAST one will have any permanent effect.

 

So what SAS code did you want to generate?

What is the goal of the data step?  What part of the code needs to change that requires a macro to generate some of the code?

 

Note if you want to use an ARRAY there is not need for a macro.

 

So if the goal is to set FLAG to TRUE if there is ever a case where VAR<n> is ever greater than < VAR<n-> then you might do something like:

data check_esp_2;
  set Base;
  array var[57];
  do index=2 to dim(var) until(flag);
    flag = (var[index] > var[index-1] );
  end;
run;

 

 

sas-innovate-2024.png

Available on demand!

Missed SAS Innovate Las Vegas? Watch all the action for free! View the keynotes, general sessions and 22 breakouts on demand.

 

Register now!

Mastering the WHERE Clause in PROC SQL

SAS' Charu Shankar shares her PROC SQL expertise by showing you how to master the WHERE clause using real winter weather data.

Find more tutorials on the SAS Users YouTube channel.

Discussion stats
  • 3 replies
  • 301 views
  • 1 like
  • 3 in conversation