Wednesday, November 25, 2015

Logical Indexing in Octave/Matlab and Python/Numpy

Octave/Matlab

Consider the following set of operations in Octave or Matlab.

Make an array.

octave:1> x=1:10
x =
1    2    3    4    5    6    7    8    9   10

Which elements of "x" are greater than 5? The result is a logical array.

octave:2> c1 = x > 5
c1 =
0   0   0   0   0   1   1   1   1   1

Which elements are less than 8?

octave:3> c2 = x < 8
c2 =
1   1   1   1   1   1   1   0   0   0

The logical combination of two logical arrays is interpreted pair-wise.

octave:4> c = c1 & c2
c =
0   0   0   0   0   1   1   0   0   0

octave:5> x(c)
ans =
6   7

Python/Numpy

Now consider doing something similar in numpy.

>>> import numpy as np
>>> x=np.arange(1,11)
>>> x
array([ 1,  2,  3,  4,  5,  6,  7,  8,  9, 10])
>>> c1 = x > 5
>>> c1
array([False, False, False, False, False,  True,  True,  True,  True,  True], dtype=bool)
>>> c2 = x < 8

So far so good. But when I say,

>>> c = c1 and c2
Traceback (most recent call last):
File "", line 1, in
ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()

The "and" command is good only to compare two bools, not arrays of bools. Therefore numpy suggests using x.any() or x.all() to collapse the vector of logical arguments to a scalar. For example.

>>> c1.all() # are all elements of c1 True?
False
>>> c1.any() # are any elements of c1 True?
True

To do an element-by-element comparison simply use np.logical_and or np.logical_or.

>>> c = np.logical_and(c1, c2)
>>> c
array([False, False, False, False, False,  True,  True, False, False, False], dtype=bool)

>>> x[c]
array([6, 7])