0

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

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

I want to test if mat1 contains only 1's or 0's, namely some 1's and some 0's, all 0's, or all 1's.

1
  • None of the answers are correctly using np.isin. stackoverflow.com/questions/57248993 is, albeit its being 6 years younger. Voting to close as it doesn't contribute to SO as the knowledge base. Commented Apr 3, 2024 at 23:23

6 Answers 6

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

9 Comments

Can you please explain what that means?
@user3333975, I added an example, I hope that makes sense.
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, 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.
@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.
|
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
>>>

5 Comments

Could you comment your code? What is happening here?
Hey, just an aside, how can I make a matrix like mat0 = np.array([[1,2,3],[4,5,6],[7,8,9]]) flatten to an array like arr0 = np.array([1,2,3,4,5,6,7,8,9])?
Is that what your code does? I think I follow. That's clever... Can I modify your existing set code to do what I want with the matrix-to-array comment I made above?
I've got a better one: sum((set(mat0.ravel())))
This makes no use of numpy, so is waaaay slower.
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

3 Comments

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.
If you use Python 2.7+ or 3.1+, you can use set literals: {1, 0} instead of set((1, 0)).
Yeah, exactly @falsetru, actually I am on 2.7.6, but just thinking the old fashioned way may be better understood.
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

2 Comments

Note: this short circuits if min is not 0.
pretty nice. And if it wasn't of int dtype, you would have issues using the equality operator as done in all other answers anyway.
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

2 Comments

Note: np.unique sorts, not an issue here (although this is slower than top soln already) but is if it's got lots of items.
fyi, pandas unique function does exactly the same as numpy but without the sorting.
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.

Comments

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.