Loren on the Art of MATLAB

Turn ideas into MATLAB

Logical Indexing – Multiple Conditions 22

Posted by Loren Shure,

I've talked about logical indexing before in some of the linked posts, but recent work makes me want to show it off again. One of the nice things about logical indexing is that it is very easy and natural to combine the results of different conditions to select items based on multiple criteria.

Contents

What is Logical Indexing?

Suppose I have an array of integers, not sorted, and want to find the ones that are less than a certain number. Here's how I can do it using the function find.

X = randperm(20)
target = 5;
X =
  Columns 1 through 13
     3     7     1    16    20    15    13     9    14     8    11    19    18
  Columns 14 through 20
     4    10     5     6    17    12     2
ind = find(X < target)
ind =
     1     3    14    20

You can see that find returns the indices into the array X that have values less than the target. And we can use these to extract the values.

Xtarget = X(ind)
Xtarget =
     3     1     4     2

Another way to accomplish the same outcome is to use the logical expression to directly perform the indexing operation. Here's what I mean.

logInd = X < target
logInd =
  Columns 1 through 13
     1     0     1     0     0     0     0     0     0     0     0     0     0
  Columns 14 through 20
     1     0     0     0     0     0     1

MATLAB returns an array that matches the elements of the array X, element-by-element holding 1s where the matching values in X are the desired values, and 0s otherwise. The array logInd is not an array of double numbers, but have the class logical.

whos logInd
  Name        Size            Bytes  Class      Attributes

  logInd      1x20               20  logical              

I can now use this array to extract the desired values from X.

XtargetLogical = X(logInd)
XtargetLogical =
     3     1     4     2

Both methods return the results.

isequal(Xtarget, XtargetLogical)
ans =
     1

Compound conditions.

Let me create an anonymous function that returns true (logical(1)) for values that are even integers.

iseven = @(x) ~logical(rem(x,2))
iseven = 
    @(x)~logical(rem(x,2))

Test iseven.

iseven(1:5)
ans =
     0     1     0     1     0

Find Values Meeting More Than One Condition

Now I would like to find the values in X that are less than target and are even. This is very natural to do with logical indexing. We have the pieces of code we need already.

compoundCondInd = (X < target) & iseven(X)
compoundCondInd =
  Columns 1 through 13
     0     0     0     0     0     0     0     0     0     0     0     0     0
  Columns 14 through 20
     1     0     0     0     0     0     1

We can see we found suitable values at locations 3 and 19. And we can extract those values next.

X(compoundCondInd)
ans =
     4     2

Did You Notice?

Did you see how easy it is to combine multiple conditions? I simply look for each of condition, getting back logical arrays, and then compute a logical array where the two input arrays are both true (via &). I could, of course, calculate a compound condition where only either one or the other condition needs to be true using logical or (via |).

A Recent Application

I recently used this in the context of finding suspect data values. I had 2 arrays, hourly temperature and speed. The problem is that when the temperature gets near or below freezing, the speed sensor might freeze. But I didn't want to delete ALL the values below freezing. So I looked for data where the temperature was sufficiently low AND the speed was very low (which could potentially mean the sensor was frozen). That way, I did not need to discard all data at low temperatures.

Have You Used Compound Indexing?

Did you do it like I did, using logical expressions? Or did you use some other techniques? What were you trying to achieve with your compound indexing? Let me know here.


Get the MATLAB code

Published with MATLAB® R2012b

1403 views (last 30 days)  | |

Comments

To leave a comment, please click here to sign in to your MathWorks Account or create a new one.