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

How to do a boundary condition in a matrix? 

 

For example : 

/*handling boundary violations*/
	if X[,1:p]<lb then X[,1:p]=lb;
	else e=0;

I have found some results with any(X)<lb 

But I absolutly want to have the row that is <lb assign to lb (and not for all of the lines). As it is a boundary condition. 

 

1 ACCEPTED SOLUTION

Accepted Solutions
Rick_SAS
SAS Super FREQ

Example data is always appreciated.

 

When you ask questions, be sure to indicate what symbols represent vectors/matrices versus scalars. I think most people who are reading your question will assume that lb is a scalar value, but I recall from a previous question that lb is a vector.

 

You need to look carefully at your IF statement to make sure it is correct. I think the left-hand side and right-hand side are both vectors. That is, the statement is

IF v1 < v2 THEN ...
where both v1 and v2 are row vectors.

 

When you make a logical decision with vectors, you should specify whether you are testing for ANY element satisfying the condition or ALL elements satisfying it.  By default, SAS/IML uses ALL elements.

Look at the following example:

v1 = {1 2 3 -4 5};
lb = {2 1 0 0 0};
if v1 < lb then v1 = lb;
print v1;

I suspect you only want to replace the elements that exceed the bounds. As KSharp says, you can use LOC for this, but you need to use the resulting index on BOTH SIDES of the assigment:

v1 = {1 2 3 -4 5};
lb = {2 1 0  0 0};
idx = loc(v1 < lb);
if ncol(idx)>0 then        /* were there any? */
   v1[ ,idx] = lb[ ,idx];  /* assign ONLY elements that satisfied the condition */
print v1;

That describes how to solve these problems in general. 

For the special problem of choosing the elementwise minimum between two vectors, SAS/IML has a special "elementwise minimum operator" ("><") which reduces the problem to a one-liner:

v1 = {1 2 3 -4 5};
lb = {2 1 0  0 0};
v1 = v1 <> lb;      /* max index operator */
print v1;

 

View solution in original post

5 REPLIES 5
Ksharp
Super User
Then you need get its index firstly .

if any(X[,1:p]<lb) then do;
idx=loc(X[,1:p]<lb);
X[idx ,1:p]=lb;
end;
Rick_SAS
SAS Super FREQ

Example data is always appreciated.

 

When you ask questions, be sure to indicate what symbols represent vectors/matrices versus scalars. I think most people who are reading your question will assume that lb is a scalar value, but I recall from a previous question that lb is a vector.

 

You need to look carefully at your IF statement to make sure it is correct. I think the left-hand side and right-hand side are both vectors. That is, the statement is

IF v1 < v2 THEN ...
where both v1 and v2 are row vectors.

 

When you make a logical decision with vectors, you should specify whether you are testing for ANY element satisfying the condition or ALL elements satisfying it.  By default, SAS/IML uses ALL elements.

Look at the following example:

v1 = {1 2 3 -4 5};
lb = {2 1 0 0 0};
if v1 < lb then v1 = lb;
print v1;

I suspect you only want to replace the elements that exceed the bounds. As KSharp says, you can use LOC for this, but you need to use the resulting index on BOTH SIDES of the assigment:

v1 = {1 2 3 -4 5};
lb = {2 1 0  0 0};
idx = loc(v1 < lb);
if ncol(idx)>0 then        /* were there any? */
   v1[ ,idx] = lb[ ,idx];  /* assign ONLY elements that satisfied the condition */
print v1;

That describes how to solve these problems in general. 

For the special problem of choosing the elementwise minimum between two vectors, SAS/IML has a special "elementwise minimum operator" ("><") which reduces the problem to a one-liner:

v1 = {1 2 3 -4 5};
lb = {2 1 0  0 0};
v1 = v1 <> lb;      /* max index operator */
print v1;

 

Rick_SAS
SAS Super FREQ

PS: As you see from my response, you do NOT need an ELSE statement for every IF statement. So you can delete all your statements else e=0; unless they are useful to you.

CerditoSalvaje
Obsidian | Level 7

Thank you Rick. And what if v1 is a matrix ? 

 

proc iml;
v1 = {1 2 3 -4 5, 0 0 0 0 0 ,3 4 5 6 7};
lb = {2 1 0  0 0};
idx = loc(v1 < lb);
if ncol(idx)>0 then        /* were there any? */
   v1[ ,idx] = lb[ ,idx];  /* assign ONLY elements that satisfied the condition */
print idx; /*problem it is not in a matrix format*/
Rick_SAS
SAS Super FREQ

LOC returns indices into the matrix, so you need to be careful if you are comparing elements of a matrix to elements of a vector. Look at this example:

proc iml;
v1 = {1 2 3 -4 5, 
      0 0 0 0 0 ,
      3 4 5 6 7};
lb = {2 1 0  0 0};

/* indicator matrix */
M = (v1 < lb);
print M;
idx = loc(v1 < lb);        /* LOC returns numbers in 1..(nrow(v1)*(ncol(v1)) */
print idx;

You can either loop over the rows of the matrix, or you can use the "elementwise maximum operator," which works for matrix-vector comparisons:

/* max index operator */
T = (v1 <> lb);
print T;

 

sas-innovate-white.png

Missed SAS Innovate in Orlando?

Catch the best of SAS Innovate 2025 — anytime, anywhere. Stream powerful keynotes, real-world demos, and game-changing insights from the world’s leading data and AI minds.

 

Register now

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