Passing value from array as a macro parameter

Accepted Solution Solved
Reply
Contributor
Posts: 62
Accepted Solution

Passing value from array as a macro parameter

Hi Everyone,

I'm trying to pass the value from array to be used as a macro parameter. Can anyone plz help with syntax to get this to work?

%macro replace (var);

      &var.New;

%mend;

data test;

input A B ANew BNew;

array _num A B ;

do over _num;

if _num ne . then  _num = %replace (_num) ;

end;

cards;

50 10 70 20

. . 30 30

1 . 5 6

2 6 10 10

;

run;



The data that I want should look like this


A             B             ANew                   BNew

70           20           70                           20

.               .            30                           30

5              .             5                              6

10           10           10                           10

Basically, if values of A or B are not missing then replace it with values from ANew and BNew respectively (I know I can set another array for ANew and BNew, but not interested in this approach but rather in using the macro).

I'm failing to pass value from array _num to macro %replace; SAS is using the literal translation of "_num" rather than its value and giving this note: "NOTE: Variable _numNew is uninitialized."


Thanks for help


Accepted Solutions
Solution
‎11-21-2014 04:08 PM
Super User
Posts: 11,134

Re: Passing value from array as a macro parameter

This works. Extra variables show steps needed. I think that part to get the name of the variable from the array reference doesn't work with the do over definition of arrays.

Also, when your macro is to return a string that shouldn't have a ; you don't want one on in macro definition.

%macro replace (var);
      &var.New
%mend;

data test;
input A B ANew BNew;
array _num A B ;
do i =1 to dim( _num);
   t = vname(_num);
   s= resolve('%replace ('||strip(t)||')') ;
   if _num ne . then  _num = vvaluex (s) ;
end;
drop i t s;
cards;
50 10 70 20
. . 30 30
1 . 5 6
2 6 10 10
;
run;

View solution in original post


All Replies
Respected Advisor
Posts: 3,156

Re: Passing value from array as a macro parameter

Is there any particular reason you have to use Macro?

data test;

     input A B ANew BNew;

     array _num A B;

     array _new ANew BNew;

     do over _num;

           if _num ne . then

                _num = _new;

     end;

     cards;

50 10 70 20

. . 30 30

1 . 5 6

2 6 10 10

;

run;

Contributor
Posts: 62

Re: Passing value from array as a macro parameter

Thanks for replay; I'm aware of the method you indicated. However, this is a sample scenario where I need to pass a value from an array to a macro in a larger piece of code, but with unfruitful results so far. so I'm trying to get help.

Respected Advisor
Posts: 3,156

Re: Passing value from array as a macro parameter

Then you need to provide more details for us to understand your need. Using Macro in the example you gave, frankly, will cause a big mess.

Super User
Posts: 5,388

Re: Passing value from array as a macro parameter

If you for some reason need to use macro, try to use the resolve() function.

Another option is to create a function instead, probably more efficient (PROC FCMP).

Data never sleeps
Solution
‎11-21-2014 04:08 PM
Super User
Posts: 11,134

Re: Passing value from array as a macro parameter

This works. Extra variables show steps needed. I think that part to get the name of the variable from the array reference doesn't work with the do over definition of arrays.

Also, when your macro is to return a string that shouldn't have a ; you don't want one on in macro definition.

%macro replace (var);
      &var.New
%mend;

data test;
input A B ANew BNew;
array _num A B ;
do i =1 to dim( _num);
   t = vname(_num);
   s= resolve('%replace ('||strip(t)||')') ;
   if _num ne . then  _num = vvaluex (s) ;
end;
drop i t s;
cards;
50 10 70 20
. . 30 30
1 . 5 6
2 6 10 10
;
run;

Super User
Posts: 19,167

Re: Passing value from array as a macro parameter

This isn't a good way to do things because it's a nightmare to code, debug, maintain...nevertheless:

_num is an array you need to pass the variable name so you'll at least need to call the vname function to pull the variable name from the array, then pass that as an argument to your macro. That part I don't know how to do, but here's the vname part for you:

data test;

input A B ANew BNew;

array _num A B ;

do over _num;

    if _num ne . then do;

        value=vname(_num);

        _num = %replace (value) ;

    end;

end;

cards;

50 10 70 20

. . 30 30

1 . 5 6

2 6 10 10

;

run;

Contributor
Posts: 62

Re: Passing value from array as a macro parameter

You guys are awesome. I realize this approach is not optimum, nevertheless it's good to know.

Super User
Super User
Posts: 6,845

Re: Passing value from array as a macro parameter

You realize that the macro will evaluate BEFORE the data step starts to run?  If not then please learn about how SAS macro processor works before trying to do something this complex.

You could call your simple macro inside of a running data step using the RESOLVE() function since your macro only performs macro logic. That is it does not generate any actual SAS code.  Use VNAME to find the actual name of the variable referenced. Use concatenation to generate the macro call. Use RESOLVE() to get result of the macro back as a string.  Pass that to VVALUEX() to get the value as a string. Then use INPUT() function to convert the value back to a number.

%macro replace (var); &var.New %mend;

data test;

  input A B ANew BNew;

  array _num A B ;

  put (_n_ A B) (= Z3.) @ ;

  do over _num;

     if _num ne . then  do;

        _num = input(left(vvaluex(resolve('%replace('||vname(_num)||')'))),32.);

     end;

  end;

  put ' -> ' (A B) (= Z3.);

cards;

50 10 70 20

. . 30 30

1 . 5 6

2 6 10 10

;

run;


_N_=001 A=050 B=010  -> A=070 B=020

_N_=002 A=. B=.  -> A=. B=.

_N_=003 A=001 B=.  -> A=005 B=.

_N_=004 A=002 B=006  -> A=010 B=010

🔒 This topic is solved and locked.

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

Discussion stats
  • 8 replies
  • 1260 views
  • 0 likes
  • 6 in conversation