Niles Bernoulli
Niles Bernoulli

Reputation: 127

Checking elements in a matrix in python

I have a matrix in scipy. And I'm trying to replace it with a 1 if it meets a certain condition, and a 0 if it doesnt.

for a in range(0,l):
      for b in range(0,l):
               if Matrix[a][b] == value:
                    Matrix[a][b] = 1
               else:
                    Matrix[a][b] = 0

My matrix is full of elements that have the "value" in it. Yet it's giving me the output as a matrix that is entirely 0's.

This worked before on a similar script. Is it perhaps something to with the structure of the matrix?

Here's how the matrix looks at first--

[ [0   1.  1.  2.]
  [1.  0.  2.  1.]
  [1.  2.  0.  1.]
  [2.  1.  1.  0.]]

When i set value == 1. I get all the 1's to 1's, and all the 2's to zero. Which is what I want.

But, when i set value == 2. I get everything to zero.

when I do all of what has been suggested.

[[ 0.  1.  1.  2.  1.  2.  2.  3.]
 [ 1.  0.  2.  1.  2.  1.  3.  2.]
 [ 1.  2.  0.  1.  2.  3.  1.  2.]
 [ 2.  1.  1.  0.  3.  2.  2.  1.]
 [ 1.  2.  2.  3.  0.  1.  1.  2.]
 [ 2.  1.  3.  2.  1.  0.  2.  1.]
 [ 2.  3.  1.  2.  1.  2.  0.  1.]
 [ 3.  2.  2.  1.  2.  1.  1.  0.]]

>>  np.where(matrix==2,1,0)
>> array([[0, 0, 0, 0, 0, 0, 0, 0],
   [0, 0, 0, 0, 0, 0, 0, 0],
   [0, 0, 0, 0, 0, 0, 0, 0],
   [0, 0, 0, 0, 0, 0, 0, 0],
   [0, 0, 0, 0, 0, 0, 0, 0],
   [0, 0, 0, 0, 0, 0, 0, 0],
   [0, 0, 0, 0, 0, 0, 0, 0],
   [0, 0, 0, 0, 0, 0, 0, 0]])

Upvotes: 4

Views: 24650

Answers (4)

Hannes Ovrén
Hannes Ovrén

Reputation: 21831

I am thinking that this could be due to floating point comparisons. You are looking for value == 2 but it seems like your matrix holds floating point values. Are you sure that all your 2.0 in your matrix is exactly 2.0 and not 1.999999999 or something similar?

Like this example (from IPython-terminal)

In [35]: A = array([1.999999999, 1.999999999])

In [36]: A
Out[36]: array([ 2.,  2.])

In [37]: A == 2
Out[37]: array([False, False], dtype=bool)

As you can see, even though the matrix A looks like it contains the exact value '2.0` it really doesn't, it is just the way it is printed.

Update: Suggested code change

To avoid the problem you could use the numpy.isclose function and simply replace your looping with

ok_mask = np.isclose(Matrix, value)
fail_mask = ~ok_mask
Matrix[ok_mask] = 1
Matrix[fail_mask] = 0

I guess this also has the benefit of probably being a bit quicker than your current loops.

Upvotes: 1

dawg
dawg

Reputation: 103754

You can use np.where to do this.

Given:

>>> matrix
array([[0, 1, 1, 2],
       [1, 0, 2, 1],
       [1, 2, 0, 1],
       [2, 1, 1, 0]])

This replaces 2 values in matrix with 0 and leaves the other values alone:

>>> np.where(matrix==2,0,matrix)
array([[0, 1, 1, 0],
       [1, 0, 0, 1],
       [1, 0, 0, 1],
       [0, 1, 1, 0]])

Or this replaces 2 values with 0 and any other value with 1:

>>> np.where(matrix==2,0,1)
array([[1, 1, 1, 0],
       [1, 1, 0, 1],
       [1, 0, 1, 1],
       [0, 1, 1, 1]])

Even:

>>> np.where(matrix==2,'  a two','not two')
array([['not two', 'not two', 'not two', '  a two'],
       ['not two', 'not two', '  a two', 'not two'],
       ['not two', '  a two', 'not two', 'not two'],
       ['  a two', 'not two', 'not two', 'not two']], 
      dtype='<U7')

Upvotes: 1

aIKid
aIKid

Reputation: 28242

I'm not familiar with scipy, but if Matrix is a normal list, i would do this:

#Assuming l is the length of Matrix
for a in range(l):
      for b in range(len(Matrix[a])):
               if Matrix[a][b] == value:
                    Matrix[a][b] = 1
               else:
                    Matrix[a][b] = 0

Here is a little demo:

>>> Matrix = [[1,2], [3,4]]
>>> value = 2
>>> l = len(Matrix)
>>> for a in range(l):
      for b in range(len(Matrix[a])):
               if Matrix[a][b] == value:
                    Matrix[a][b] = 1
               else:
                    Matrix[a][b] = 0


>>> Matrix
[[0, 1], [0, 0]]

Upvotes: 0

user2357112
user2357112

Reputation: 280291

If you actually have a matrix there, rather than an ndarray, then

Matrix[a]

is a 1-row matrix, and 2D. Similarly,

Matrix[a][b]

is also a matrix (or an IndexError, since Matrix[a] only has 1 row). You need to use

Matrix[a, b]

to get the elements. This is one of the reasons why using matrices can be awkward. Note that you could just use

Matrix == value

to get a matrix of booleans, and then use astype to convert it to the type you want. This would be less code, and it'd run faster. Thus, if your dtype is int32, the whole loopy thing you've posted could be replaced by

return (Matrix == value).astype(numpy.int32)

or if you really want to modify the array in place, you can use the numpy.equal ufunc with an out parameter:

numpy.equal(Matrix, value, out=Matrix)

Upvotes: 6

Related Questions