DATA Step, Macro, Functions and more

%Scan function error

Reply
Occasional Contributor
Posts: 7

%Scan function error

%MACRO FIND_CLOSEST_VALUE(limOrDedOption,limorDedValue);

     %LET numOptions = %Sysfunc(Countw(&limOrDedOption.));

     limOrDedSetFlag = 'N';

     %DO curLimOrDed = 1 %TO &numOptions.;

          IF limOrDedSetFlag = 'N" AND &curlimOrDed > 1 THEN DO;

               lwrVal = %Scan(&limOrDedOption., &curLimOrDed. - 1);

               uprVal = %Scan(&limOrDedOption., &curLimOrDed.);

               IF &limOrDedValue. < uprVal THEN DO;

                    IF (&limOrDedValue. - lwrVal)/(uprVal - lwrVal) < 0.5 THEN &limOrDedValue = lwrVal;

                    ELSE &limOrDedValue = uprVal;

               END;

          END;

     %END;

%MEND;    

Receiving an error:

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

prevLimOrDed

ERROR: Argument 2 to macro function %SCAN is not a number.

 

Error occurs on the lwrVal. uprVal is fine. It's almost as if the if condition is not met on the &curLirOrDed > 1

Any ideas?

   

 

Trusted Advisor
Posts: 1,607

Re: %Scan function error

Can we see the relevant portions of the code that you used to call this macro?

Occasional Contributor
Posts: 7

Re: %Scan function error

%LET numArray = 200000 300000 500000 1000000 2000000;

DATA TEST;

     SET inforce;

     %FIND_CLOSEST_VALUE(&numArray, testValue);

RUN;

Super User
Posts: 10,466

Re: %Scan function error

This does not pass the VALUE of testValue variable to the macro, it passes the TEXT value "testValue";

Occasional Contributor
Posts: 7

Re: %Scan function error

testValue is actually a dataset column. The macro should check what the value in the testValue column is.

For example, say the value is 60, but acceptable values are 50 and 100.

The macro calculates if 60 is closer to 50 or 100, and based on that, resets the testValue to 50.

Contributor
Posts: 24

Re: %Scan function error

there are different Errors.

  1. the macro does not do, what is intended. The limOrDedSetFlag was not changed, in the loop, if the Operation was succesfull. So always writes the next loop over the result of the previous loop.
  2. the Expression "&curLimOrDed. - 1" in the %scan-function must be "%eval(&curLimOrDed. - 1)"
  3. The test is very complicated. Why do you not simply compare the differences from  limorDedValue to lower bound and upper bound.

%MACRO FIND_CLOSEST_VALUE(limOrDedOption,limorDedValue);

%LET numOptions = %Sysfunc(Countw(&limOrDedOption.,%str( )));

limOrDedSetFlag = 'N';

  /* probe of less or equal as the smallest value */

if &limOrDedValue. <= %Scan(&limOrDedOption., 1,%str( )) then do;

      &limOrDedValue. = %Scan(&limOrDedOption., 1,%str( ));

           limOrDedSetFlag = 'Y';

end;

    /* probe of equal or greater as the highest value */

else if &limOrDedValue. >= %Scan(&limOrDedOption., -1,%str( )) then do;

   &limOrDedValue. = %Scan(&limOrDedOption., -1,%str( ));

   limOrDedSetFlag = 'Y';

end;

else do;

/* the value must be between 2 values or equal a value of the list*/

      %DO curLimOrDed = 2 %TO &numOptions.;

      IF limOrDedSetFlag = 'N' THEN DO;

        lwrVal =%Scan(&limOrDedOption., %eval(&curLimOrDed. - 1));

      uprVal =%Scan(&limOrDedOption., &curLimOrDed.);

      IF (lwrval <= &limOrDedValue.) and (&limOrDedValue.) <= uprVal THEN DO;

        IF (&limOrDedValue. - lwrVal) < (uprVal - &limOrDedValue.)

          THEN &limOrDedValue. = lwrVal;

                   ELSE  &limOrDedValue. = uprVal;

        limOrDedSetFlag = 'Y';

      END;

    END;

  %END;

end;

%MEND;   

/* usage */

%LET
numArray = 200000 300000 500000 1000000 2000000;

optionsmprint;

DATA TEST;

   testvalue1=  34000;

   testvalue2= 340000;

   testvalue3=3400000;

%FIND_CLOSEST_VALUE(&numArray., testValue1);

%FIND_CLOSEST_VALUE(&numArray., testValue2);

%FIND_CLOSEST_VALUE(&numArray., testValue3);

RUN;

Super User
Super User
Posts: 7,392

Re: %Scan function error

Hi,

Have you tried:

               lwrVal = %Scan(&limOrDedOption., %eval(&curLimOrDed. - 1));

If so maybe put options mlogic mprint symbolgen; on and see what the macro variables resolve to.

Occasional Contributor
Posts: 7

Re: %Scan function error

yes, I tried %eval and i tried put(&curLimOrDed,1.) - 1. I am receiving the exact same error =(

Super User
Super User
Posts: 7,392

Re: %Scan function error

Well, couple of things:

- You have a typo in the macro, IF limOrDedSetFlag = 'N" AND - double quotes after the N.

- Secondly you only want to do the %do loop from 2 to numoptions, other 1 with -1 = 0 which is an invalid scan array.

Note, can't actually test this as no data provided.

So change: %DO curLimOrDed = 2 %TO &numOptions.;

Occasional Contributor
Posts: 7

Re: %Scan function error

For some reason cannot copy paste in this editor. I typed 'N" up, it is actually a 'N'.

As for the second comment, I have a condition to execule when &curLimOrDed = 1 and when &curLimOrDed > 1. The

%Scan(&limOrDedOption, &curLimOrDed. -1 ) executes only when :

  IF limOrDedSetFlag = 'N" AND &curlimOrDed > 1 THEN DO;

Super User
Super User
Posts: 7,392

Re: %Scan function error

Ok, another thought, what is the prevLimOrDed, mentioned in the error message, I don't see this in the macro or code.  Also, have you tried putting options mlogic mprint symbolgen; on and seeing what is being generated?

Occasional Contributor
Posts: 7

Re: %Scan function error

The prevLimOrDed was me testing. sorry, removed it, still getting an error:

           

               

Super User
Super User
Posts: 7,392

Re: %Scan function error

Perhaps start again, post the actual code (including call), the actual log text with the error, and if possible some test data which triggers the error.  Will have a look tomorrow.

PROC Star
Posts: 7,356

Re: %Scan function error

MARY9999: Do you have to use a macro for this? It can be done easily within a datastep. E.g.:

DATA TEST;

     SET sashelp.class (rename=(age=testValue));

     array limOrDedOption(8) _temporary_ (10.4,11.6,12.4,13.6,14.4,15.6,16.4,17.6);

     do _n_=2 to dim(limOrDedOption);

       if limOrDedOption(_n_) ge testValue then do;

         if testValue+(limOrDedOption(_n_)-limOrDedOption(_n_-1))/2 gt limOrDedOption(_n_)

          then closest=limOrDedOption(_n_);

         else closest=limOrDedOption(_n_-1);

         leave;

       end;

       else if _n_ eq dim(limOrDedOption) then closest=limOrDedOption(_n_);

     end;

RUN;

Occasional Contributor
Posts: 7

Re: %Scan function error

Ideally yes, i have t odo this for 20 different variables.

Ask a Question
Discussion stats
  • 16 replies
  • 440 views
  • 0 likes
  • 6 in conversation