BookmarkSubscribeRSS Feed
🔒 This topic is solved and locked. Need further help from the community? Please sign in and ask a new question.
Fluorite | Level 6

## compare matrix value under %if statement

Hello,

I want to use a list of values to determine what matrix operations that need to be performed.

I also need to create a sequence of new matrices based on these operation.

I tried to use macro and proc iml to achieve this, but statement x[%eval(&j.+1)] = 1 did not give expected results. It seems it is always false regardless if the value in x[position]. Can someone please explain to me how the syntax should be? Thanks.

x = {0 1 0 1 0 0};

%do i = 0 %to 5;
%if x[%eval(&i.+1)] = 1 %then
%do;
m%eval(&i.+1) = m&i. * another_matrix_&i.;
%end;
%else
%do;
m%eval(&i.+1) = m0;
%end;

%end;

1 ACCEPTED SOLUTION

Accepted Solutions
SAS Super FREQ

## Re: compare matrix value under %if statement

You do not show your entire program, so it is difficult to know what you are trying to accomplish. Why are you creating these matrices m1, m2,.. m6? Are they all the same size? Do you only need them one at a time, or are you going to require them all at the same time to perform some computation?

In general, because SAS/IML is a complete programming language, it is rarely necessary to use macro loops in IML programs. Regarding the interaction between the macro language and SAS/IML, I encourage you to read "Macros and loops in the SAS/IML language"

for some tips and insights.

My advice: If the matrices are the same size, use an array of matrices is to pack them into rows of a big matrix.  The alternative (which also works if the matrice are different sizes) is to create a list of matrices. Neither method requires using macro loops.

7 REPLIES 7
SAS Super FREQ

## Re: compare matrix value under %if statement

You do not show your entire program, so it is difficult to know what you are trying to accomplish. Why are you creating these matrices m1, m2,.. m6? Are they all the same size? Do you only need them one at a time, or are you going to require them all at the same time to perform some computation?

In general, because SAS/IML is a complete programming language, it is rarely necessary to use macro loops in IML programs. Regarding the interaction between the macro language and SAS/IML, I encourage you to read "Macros and loops in the SAS/IML language"

for some tips and insights.

My advice: If the matrices are the same size, use an array of matrices is to pack them into rows of a big matrix.  The alternative (which also works if the matrice are different sizes) is to create a list of matrices. Neither method requires using macro loops.

Diamond | Level 26

## Re: compare matrix value under %if statement

One mistake is that the macro processor is not needed here, and indeed produces incorrect results. If you use a PROC IML DO loop and no macro %IF statements, the code works fine.

This brings up an important concept: before writing any macros, you need to have code that works without macros. if you can't get the code to work without macros, then it will never work with macros.

Why doesn't

``%if x[%eval(&i.+1)] = 1 %then %do;``

work as you think it should? Because in an %IF statement, the macro processor is comparing text strings. When &i is 1, then x[%eval(&i+1)] is the text string x[2] which is not equal to the text string 1. The macro processor does not use the matrix value of x[2] here.

However if you use the IML IF command

``if x[&i+1]=1 then do;``

then the IML language processor knows that the value of matrix x in position 2 is indeed equal to 1.

Again, you need to produce working code without macros before you try to write macros. And indeed follow the advice from @Rick_SAS which would let you avoid using macros within PROC IML in most situations.

--
Paige Miller
Fluorite | Level 6

## Re: compare matrix value under %if statement

Thank you for the feedback.
If without using the macro %do statement, is there a way to create a series of matrix by the loop counter? For example if I have 10 by 10 matrix, and based on the switch/condition, m1 may need to use m0 to do matrix multiplication with another matrix, or sometimes needs to do addition/subtraction...etc. The following code can achieve this:
m%eval(&i.+1) = m&i. * another_matrix_&i.;
What would be an alternative may to construct new matrices just inside do loop? Thanks.

%do i = 0 %to 5;
%if x[%eval(&i.+1)] = 1 %then
%do;
m%eval(&i.+1) = m&i. * another_matrix_&i.;
%end;
%else
%do;
m%eval(&i.+1) = m0;
%end;
%end;
Diamond | Level 26

## Re: compare matrix value under %if statement

@SAS_Dev wrote:
Thank you for the feedback.
If without using the macro %do statement, is there a way to create a series of matrix by the loop counter?

@Rick_SAS has explained how to do this already in this thread, and linked to a blog post (or maybe several blog posts) on it as well.

Update/correction: my post earlier implied you should use a IML DO loop instead of a macro %DO loop, which is incorrect. A macro %DO loop could work here if you use the IML IF statement and not the macro %IF statement, but again going back to the comments from Rick, it still isn't needed. Following RIck's suggestion avoids all this unpleasant and difficult switching between languages (IML and macro language) and getting them to interact correctly (which isn't easy to do and certainly should be avoided by beginners, and also should be avoided by experienced programmers like me unless there is no other possibility).

--
Paige Miller
Fluorite | Level 6

## Re: compare matrix value under %if statement

Thanks. I will read and try it out.
The reason I used loop it's because the furture matrices are depends on by decisions and the values of previous/past matrices.
SAS Super FREQ

## Re: compare matrix value under %if statement

There are many ways in SAS/IML to address the issues you discuss. If you state what you are trying to accomplish and provide an example, I am sure someone will be able to help you.

Fluorite | Level 6

## Re: compare matrix value under %if statement

Thank you for the posts. I think I got the syntax to work now, with your suggestion of using lists to store matrices.
For a list of transformation matrices, I have loaded them into a list (TRANS) since they are predefined.
Then inside a loop, I can use another list s to store values represent a condition (i.e. if = 1, then multiply the transformation matrix, if = 0, then do other operations). Each counter value represents a value in time, i.e. i = 1 represents first month, i = 2 represents second month...etc.
In the list form I can still reference previous month (i) result to carry calculation forward (i+1).
I wasn't able to use \$ symbol to store or call values from list, but the function ListSetItem and ListGetItem seems to be working. Thank you again.

do i = 1 to 6;
if s[i] = 1 then
do;
call ListSetItem(M, i+1, ListGetItem(M, i) * ListGetItem(TRANS, i));
end;
else
do;
call ListSetItem(M, i+1, ListGetItem(M, 1));
end;
end;
From The DO Loop
Want more? Visit our blog for more articles like these.
Discussion stats
• 7 replies
• 575 views
• 4 likes
• 3 in conversation