Obsidian | Level 7

## Matrix condition

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

## Re: Matrix condition

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;``````

5 REPLIES 5
Super User

## Re: Matrix condition

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

## Re: Matrix condition

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;``````

SAS Super FREQ

## Re: Matrix condition

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.

Obsidian | Level 7

## Re: Matrix condition

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*/``````
SAS Super FREQ

## Re: Matrix condition

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;
``````

From The DO Loop