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

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
Rick_SAS
SAS Super FREQ

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.

 

 

 

View solution in original post

7 REPLIES 7
Rick_SAS
SAS Super FREQ

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.

 

 

 

PaigeMiller
Diamond | Level 26

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
SAS_Dev
Fluorite | Level 6
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;
PaigeMiller
Diamond | Level 26

@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
SAS_Dev
Fluorite | Level 6
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.
Rick_SAS
SAS Super FREQ

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.

SAS_Dev
Fluorite | Level 6
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;

sas-innovate-2024.png

Don't miss out on SAS Innovate - Register now for the FREE Livestream!

Can't make it to Vegas? No problem! Watch our general sessions LIVE or on-demand starting April 17th. Hear from SAS execs, best-selling author Adam Grant, Hot Ones host Sean Evans, top tech journalist Kara Swisher, AI expert Cassie Kozyrkov, and the mind-blowing dance crew iLuminate! Plus, get access to over 20 breakout sessions.

 

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
  • 7 replies
  • 575 views
  • 4 likes
  • 3 in conversation