BookmarkSubscribeRSS Feed
Dima
Calcite | Level 5

Hello,

I have defined an IML function which takes 2 arguments : one as numeric, the other as character.

proc iml;

     age_vect=J(10,1,10);
     text_vect=J(10,1,"YES");

     start test(age,text);
          if text="NO" then
               temp=age+0;
          else if text="YES" then
               temp=age+10;
          return(temp);
     finish test;

     Result_1=test(10,"YES");

     Result_2=apply("test",age_vect,text_vect);

quit;

I want to apply this function to vectors, but it doesn't work (Result_2).

But this function will work if i try to calculate Result_1.

Is it impossible to pass vectors of characters to IML function?

5 REPLIES 5
IanWakeling
Barite | Level 11

I think the answer may be that  the APPLY function is not designed to work with modules that take text arguments, however it doesn't always make this clear.   For example the following code runs without error but returns a text matrix with a single element.

start uc(t);
   return(upcase(t));
finish;

cin={"a","b","c"};
cout=apply("uc",cin);
print cout;

Have a look at the CHOOSE function as it can be used to get what you want without writing a module.  For example:

Result_2=choose(text_vect="YES", age_vect+10, age_vect);

IanWakeling
Barite | Level 11

I did a little more investigation, my code above does return a 3x1 text matrix, but the second and third elements are blank.  (Rick can you investigate this please?).

Dima
Calcite | Level 5

Thank you for your suggestion about the CHOOSE function that I didn't know before. It could be helpful but not in my case.

The code above is not what I really want to do, my function is much more complex so I can't find an equivalent using CHOOSE function.

For the moment, I make my function work by coding as numbers the different strings I want to pass to my function. But that way, the code is less understandable.

IanWakeling
Barite | Level 11

The APPLY function is really nothing more than an implied loop over all the elements of a matrix, so instead of your suggested approach, you could write an explicit loop over each element.  Along the lines of:

new_age=age_vect;

do i=1 to nrow(text_vect);

    if text_vect="YES"  then new_age=new_age+10;

end;

Rick_SAS
SAS Super FREQ

I agree that there seems to be a problem with calling APPLY with character arguments.

There's no need to recode anything: just use a loop to call the scalar function that you've already written. It's not as general, but it should work adequately.

start MyApply(age_array,text_array);
   temp = J(nrow(age_array),1);
   do i = 1 to nrow(age_array);
      age = age_array;
      text = strip(text_array);

      temp = test(age, text);
   end;
   return(temp);
finish;

age_vect = {1,2,3,4,5};
text_vect = {YES, NO, NO, NO, YES};
r = MyApply(age_vect, text_vect);
print r;

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!

Multiple Linear Regression in SAS

Learn how to run multiple linear regression models with and without interactions, presented by SAS user Alex Chaplin.

Find more tutorials on the SAS Users YouTube channel.

From The DO Loop
Want more? Visit our blog for more articles like these.
Discussion stats
  • 5 replies
  • 1311 views
  • 0 likes
  • 3 in conversation