DATA Step, Macro, Functions and more

Incrementation of a macro variable

Accepted Solution Solved
Reply
Regular Learner
Posts: 1
Accepted Solution

Incrementation of a macro variable

Hello,

 

I am trying to increment a macro variable, and keep getting the "A character operand was found in the %eval function or %if condition where numeric expected....

 

**create an incrementer, so you can rank things, and some macro variables, for rank creation;
%global nihssbrankvar ninetyrankvar rank3mrankvar;
%let rank3mrankvar = 1;
%let ninetyrankvar = 1;
%let nihssbrankvar = 1;

 

**macro to increment my macrovariables;

%macro incrementvar(vartoincrement);
%let vartoincrement = %eval(&vartoincrement. + 1);
%mend;


**now lets generate a ranking for everyone, based on their rankin 3 month score;
proc sort data=mydata;
by rank3m;
run;

 

**now, let's apply this ranking;

data myranked;
set mydata;
by rank3m;

 

rank3m_rank = &rank3mrankvar.;

 

if last.rank3m=1 then do;
%incrementvar(rank3mrankvar);
charRank3m = put(last.rank3m, 8.); *This is just a test line, to ensure that last.Rank3m is flagging when i expect it is;

 

end;


run;

 

ugh I've been literally beating my head on a wall for a day, it is causing me some serious anxiety.

 

There are a couple of other posts I have found, which helped point me towards using %eval in the first place (for example) but were not like my issue and I was unable to apply to my own. I want to simply increment an integer macro variable whenever I want to, and my macro to do so is expecting an integer? But, i verify in a datastep that my macro variable rank3m_rank (which is being set equal to my macro varible I am trying to increment, &rank3mrankingvar., is indeed a numeric and not a char)

 

Thanks so much


Accepted Solutions
Solution
‎04-08-2016 06:53 PM
Super User
Super User
Posts: 6,495

Re: Incrementation of a macro variable

Let's just look at your stated objective of creating a utility macro that will increment a given macro variable by one and ignore the irrelevant data step code as just part of your attempt to debig your problem.  Here is your proposed macro definition

%macro incrementvar(vartoincrement);
  %let vartoincrement = %eval(&vartoincrement. + 1);
%mend;

The %LET statement looks fine if you just wanted to increment a variable named VARTOINCREMENT.  But if you are trying to create a macro takes as input the Name of a macro variable that you want to increment then you need to change this code becuase it is currently trying to add one to the NAME of the macro variable and store the result back into the macro variable that holds the input to the macro.

 

What you did was like this:

%let X=1;
%let NAME=X;
%let NAME = %EVAL(X + 1);

So first you are trying to add one to the string X, which won't work.  To fix that we need to use the vlaue of macro variable whose name is the value of the macro variable NAME.  To do that we need to use &&&NAME.

 

Then you are trying to store the result back into the variable NAME instead of into the variable  X.  To fix that we need to replace NAME with &NAME. 

 

So now your macro looks like this:

%macro incrementvar(vartoincrement);
  %let &vartoincrement = %eval(&&&vartoincrement. + 1);
%mend;

 

View solution in original post


All Replies
Super User
Posts: 17,743

Re: Incrementation of a macro variable

Is your %let statement missing an & on the first reference to the macro variable?

Super User
Posts: 10,460

Re: Incrementation of a macro variable

I suspect your issue is with this:

%incrementvar(rank3mrankvar);

 

the macro is processing the text value rank3mrankvar.

You may have meant

%incrementvar(&rank3mrankvar);

 

I would seriously examine the whole process as using a macro variable to set values inside a data step is likely not doing what you think it is.

The data step compiles with values found the first time, it does NOT increment and recompile with a changed value.

 

I think that you may be attempting to create a convoluted RETAIN.

Is something like this what your attempting to accomplish?

data myranked;
   set mydata;
   by rank3m;
   Retain  rank3m_rank  1;
   if last.rank3m=1 then do;
     Rank3m_rank +1;
     charRank3m = put(last.rank3m, 8.); *This is just a test line, to ensure that last.Rank3m is flagging when i expect it is;
   end;
run;
Trusted Advisor
Posts: 1,115

Re: Incrementation of a macro variable

[ Edited ]

I think, the reason for the error message "A character operand was found ..." is the incorrect macro definition, as Reeza had noticed already. Indeed, there were three ampersands missing:

%macro incrementvar(vartoincrement);
%let &vartoincrement = %eval(&&&vartoincrement + 1);
%mend;

/* Test the macro */
%let testmv=16;
%incrementvar(testmv);
%put &=testmv;

But I fully agree with ballardw that you probably don't even need this macro, because it wouldn't help you anyway in a data step. Most likely you'll be better off limiting your program to non-macro code.

Super User
Posts: 6,927

Re: Incrementation of a macro variable

Before you waste further brain cycles, consider this:

 

A macro will always execute before the data step runs (or after the data step, if you call it with call execute), so the incrementation of a macro variable will happen before your datastep code executes at all.

But you can generate valid data step incrementation code dynamically with a macro, if you need to respond to conditions that exist before said data step is reached.

 

So my best guess is that you do not need a macro at all, unless you have identical code that is used in several data steps, or need to iteratively run the step(s).

---------------------------------------------------------------------------------------------
Maxims of Maximally Efficient SAS Programmers
Solution
‎04-08-2016 06:53 PM
Super User
Super User
Posts: 6,495

Re: Incrementation of a macro variable

Let's just look at your stated objective of creating a utility macro that will increment a given macro variable by one and ignore the irrelevant data step code as just part of your attempt to debig your problem.  Here is your proposed macro definition

%macro incrementvar(vartoincrement);
  %let vartoincrement = %eval(&vartoincrement. + 1);
%mend;

The %LET statement looks fine if you just wanted to increment a variable named VARTOINCREMENT.  But if you are trying to create a macro takes as input the Name of a macro variable that you want to increment then you need to change this code becuase it is currently trying to add one to the NAME of the macro variable and store the result back into the macro variable that holds the input to the macro.

 

What you did was like this:

%let X=1;
%let NAME=X;
%let NAME = %EVAL(X + 1);

So first you are trying to add one to the string X, which won't work.  To fix that we need to use the vlaue of macro variable whose name is the value of the macro variable NAME.  To do that we need to use &&&NAME.

 

Then you are trying to store the result back into the variable NAME instead of into the variable  X.  To fix that we need to replace NAME with &NAME. 

 

So now your macro looks like this:

%macro incrementvar(vartoincrement);
  %let &vartoincrement = %eval(&&&vartoincrement. + 1);
%mend;

 

☑ This topic is SOLVED.

Need further help from the community? Please ask a new question.

Discussion stats
  • 5 replies
  • 1687 views
  • 4 likes
  • 6 in conversation