0

Let's say I've got a matrix like this:

mat1 = np.array([1,0,1], [1,1,0], [0,0,0]);

And I've got another one like this:

mat2 = np.array([0,1,0], [0,0,1], [1,1,1]);

I want to detect if something like

np.add(mat1, mat2);

has only 1's or 0's, namely some 1's and some 0's, all 0's, or all 1's.


n.b. - Comment your code.

user3333975
  • 125
  • 10

6 Answers6

4

Use numpy.all, numpy.any:

  • all 0: np.all(mat == 0)
  • all 1: np.all(mat == 1)
  • some 0: np.any(mat == 0)
  • some 1: np.any(mat == 1)

>>> mat1 = np.array([[1,0,1], [1,1,0], [0,0,0]])
>>> mat2 = np.array([[0,1,0], [0,0,1], [1,1,1]])

>>> np.all(mat1 == 0)
False
>>> np.any(mat1 == 0)
True
>>> np.all(mat1 == 1)
False
>>> np.any(mat1 == 1)
True

>>> mat3 = mat1 + mat2
>>> mat3
array([[1, 1, 1],
       [1, 1, 1],
       [1, 1, 1]])
>>> np.all(mat3 == 1)
True

UPDATE

To check whether the array contains only 1 or 0, nothing else, use following:

>>> mat1 = np.array([[1,0,1], [1,1,0], [0,0,0]])
>>> mat2 = np.array([[0,1,2], [3,4,5], [6,7,8]])
>>> np.all((mat1 == 0) | (mat1 == 1))
True
>>> np.all((mat2 == 0) | (mat2 == 1))
False
falsetru
  • 357,413
  • 63
  • 732
  • 636
  • Can you please explain what that means? – user3333975 Mar 06 '14 at 05:19
  • @user3333975, I added an example, I hope that makes sense. – falsetru Mar 06 '14 at 05:20
  • I mean, what if I add them and all but one is 0 while the rest are 1's? I don't follow--yet. – user3333975 Mar 06 '14 at 05:22
  • @user3333975, `mat1 == 0` returns array that consist of `True`, `False` items. `numpy.all` returns True only if all items are True. `numpy.any` returns if there's any True. – falsetru Mar 06 '14 at 05:22
  • @user3333975, Let's call the added array as `a`, and it contains 8 `1` and 1 `0` as items. `numpy.all(a == 0) == False`, `numpy.all(a == 1) == False`, `numpy.any(a == 0) == True`, `numpy.any(a == 1) == True`. – falsetru Mar 06 '14 at 05:24
  • @user3333975, Sorry, I don't understand what the `bust` mean. (I'm not a native speaker). It would be great if you explain what the word `bust` mean here. – falsetru Mar 06 '14 at 05:25
  • The matrix has to have only 1's and 0's--in ANY combination. If I add matrices together and I get an integer in any cell that is not 1 or 0, then this is considered a bad result--a "bust." I want to detect if any given matrix has only 1's and 0's for each element. – user3333975 Mar 06 '14 at 05:29
  • Can you method detect if `mat1` contains only 1's and 0's? – user3333975 Mar 06 '14 at 05:32
  • @user3333975, I see. I misunderstood your question. Here's the solution you want: `np.all((mat1 == 0) | (mat1 == 1))`. I will update the answer soon. – falsetru Mar 06 '14 at 05:32
2

Simply:

In [6]:

set((mat1+mat2).ravel()).issubset(set((1,0)))
Out[6]:
True

In [7]:

mat3 = np.array([[0,5,0], [0,0,1], [1,1,1]])
set((mat1+mat3).ravel()).issubset(set((1,0)))
Out[7]:
False
CT Zhu
  • 52,648
  • 17
  • 120
  • 133
  • Add `mat1` and `mat2` together, `ravel()` means to return a flattened view (1 dimension). Then we make a `set()` out of it. When the set of the resulting array is `set((1))`, `set((1,0))` or `set((0))`, the resulting set is a subset of the `set((1,0))`, which means the resulting array only have 1 and 0's. See the new example added. – CT Zhu Mar 06 '14 at 05:50
  • If you use Python 2.7+ or 3.1+, you can use set literals: `{1, 0}` instead of `set((1, 0))`. – falsetru Mar 06 '14 at 05:51
  • Yeah, exactly @falsetru, actually I am on 2.7.6, but just thinking the old fashioned way may be better understood. – CT Zhu Mar 06 '14 at 05:53
2

How about this:

>>> def check(matrix):
...     # flatten up the matrix into one single list
...     # and set on the list it should be [0,1] if it
...     # contains only 0 and 1. Then do sum on that will 
...     # return 1
...     if sum(set(sum(matrix,[]))) > 1:
...         return False
...     return True
...
>>>
>>> check([[1,0,1], [1,1,0], [0,0,0]])
True
>>> check([[1,0,1], [1,1,0], [0,0,2]])
False
>>> check([[1,0,1], [1,1,0], [0,0,3]])
False
>>>
James Sapam
  • 16,036
  • 12
  • 50
  • 73
1

If you know it's int dtype, then (suprisingly) it's faster to check the max and min (even without doing these operations simultaneously):

In [11]: m = np.random.randint(0, 2, (10, 10))

In [12]: %timeit np.all((m == 0) | (m == 1))
10000 loops, best of 3: 33.7 µs per loop

In [13]: %timeit m.dtype == int and m.min() == 0 and m.max() == 1
10000 loops, best of 3: 29.8 µs per loop

In [21]: m = np.random.randint(0, 2, (10000, 10000))

In [22]: %timeit np.all((m == 0) | (m == 1))
1 loops, best of 3: 705 ms per loop

In [23]: %timeit m.dtype == int and m.min() == 0 and m.max() == 1
1 loops, best of 3: 481 ms per loop
Community
  • 1
  • 1
Andy Hayden
  • 359,921
  • 101
  • 625
  • 535
1

You can use unique

import numpy as np
mat1 = np.array([[1,0,1], [1,1,0], [0,0,0]])

np.unique(mat1)
# array([0, 1])
1 in np.unique(mat1)
# True
0 in np.unique(mat1)
# True
np.unique(mat1) == [0, 1]
# array([ True,  True], dtype=bool)

You can also use setdiff1d

np.setdiff1d(mat1, [0, 1])
# array([], dtype=int64)
np.setdiff1d(mat1, [0, 1]).size
# 0
YXD
  • 31,741
  • 15
  • 75
  • 115
0

Check this out: np.sum(np.unique(mat0.ravel()))


So, mat0.ravel() does this:

[[1,0,0],[0,0,0],[1,1,0]] ---> [1,0,0,0,0,0,1,1,0]

This new object is an array, namely the [1,0,0,0,0,0,1,1,0] object above. Now, np.unique(mat0.ravel()) finds all the unique elements and sorts them and puts them in a set, like this:

[1,0,0,0,0,0,1,1,0] ---> {0,1}

From here if one applies np.sum on this, namely np.sum(np.unique(mat0.ravel())) we get the sum of the contents of the set, so a good condition to check if only a 0 or 1 in each and every cell in matrix is the following:

np.sum(np.unique(mat0.ravel())) > 1

n.b. - This is only for non-negative integers.

user3333975
  • 125
  • 10