4

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]])
8
  • can you ua give your matrix so that we can offer some help Commented Nov 20, 2013 at 5:56
  • What is the value of l? Commented Nov 20, 2013 at 5:57
  • 2
    Standard debugging protocol: before the comparison which isn't succeeding the way you think it should, print everything out. print(a,b,repr(Matrix[a][b]), type(Matrix[a][b]), repr(value), type(value)). If the matrix is numerical, you can also add print(Matrix[a][b]-value). You'll either see a bunch of output which will be useful, or you might see nothing at all, which would tell you something else. Commented Nov 20, 2013 at 5:58
  • The next time you encounter mysterious problems like these, use a debugger such as pdb. It's really simple to use; just insert import pdb;pdb.set_trace() which starts the debugger at wherever you insert it. Then in the debugger you can run print a,b to view the variables and print Matrix[a][b] to find out the value of that element of the matrix. You can use next to progress to the next line of the code. That way you can find out what the code is actually doing. For more information on the commands use the help command. Commented Nov 20, 2013 at 6:00
  • What is the dtype of this array? The lack of commas is odd... Commented Nov 20, 2013 at 6:53

4 Answers 4

6

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)
Sign up to request clarification or add additional context in comments.

7 Comments

Why do you have to do Matrix[a,b]? You can set up a 2d array so that you have to use Matrix[a][b], by using a matrix full of matricies. I didn't know there was another way.
@JFA: Because 1-dimensional indexing of a matrix produces a matrix. Thus, two successive 1D indexing operations, as in Matrix[a][b], also produces a matrix. You may be thinking of ndarrays, which work as you'd expect.
I am lost in what you're saying. Your last line does what exactly? I want my output to be boolean (but in the 1's and 0's sense. not the true or false sense). Also I'm not getting index errors of any sort from what I was doing.
@NilesBernoulli: You didn't get an index error because of your other bug, the 1/l thing. The last line does a broadcasted comparison of Matrix and value, checking whether each element is equal to the given value, and stores the results of the comparison back into Matrix, coercing the boolean true/false results to 1/0.
The comments under the question say the data is the ouput of scipy.spatial.distance.cdist, making it an array and not a matrix.
|
1

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')

4 Comments

np.where is working well to find the values, but when I try to give the condition where if matrix!=2 things go chaotic. My matrix element values have periods after them. Is that a problem?
What dtype is the array?
look at the new edit Im about to post. One second. edit: there it is.
I got it. I had a line where I did np.square(matrix). I commented that out, and replaced value with sqrt(value), and it worked beautifully. thank you very much.
1

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.

2 Comments

+1. This type of inaccuracy is very likely when the values have been calculated rather than set explicitly. The usual way around this is to instead test whether the values are 'close enough', which depends on the accuracy of the original measurements - but, eg, if your data is exact to 2 decimal places, then you can do np.abs(array - 2) < 0.01.
I think using numpy.isclose is probably better. I'll update my answer.
0

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]]

2 Comments

@NilesBernoulli: You probably screwed up typing it. As posted, this answer does not have a syntax error (though it does have a logical error).
Thanks but this isn't working still. So far it's replacing it only if when value is set = 1. but not for other values (that are clearly in the matrix). I'll make an edit. One second.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.