2

I'm using numpy for the first time. I am trying to achieve the following:

There are 2 arrays:

a = np.array([[1, 3], [2, 5], [1, 2], [2, 1], [1,6]])
b = np.array([[3, 5], [1, 2]])

I need to check if ANY pair (or a row in other words) in array b is present in array a, in the same order (as in, [1, 2] is not to be considered same as [2, 1])

The above example should return True since both a and b contain [1, 2]

I've tried:

for [x, y] in b
    if [x, y] in a

and:

if (a == b).all(1).any() # --> This throws "AttributeError: 'bool' object has no attribute 'all'"

but failed.

Thanks in advance

0

3 Answers 3

6

Let do it the numpyic way (loops are not advised with numpy). Add a dimension using None to let the numpy do the correct broadcasting, then use any and all along correct axis:

(a==b[:,None]).all(-1).any()

Output for sample input in question:

True
Sign up to request clarification or add additional context in comments.

Comments

4

This solution use np.ravel_multi_index to avoid broadcasting. If your array is big, this is helpful since it doesn't use broadcasting

d = np.maximum(a.max(0), b.max(0))+1
np.in1d(np.ravel_multi_index(a.T,d), np.ravel_multi_index(b.T,d)).any()

Out[71]: True

This solution is also able to give position of the row in a where it matches

np.nonzero(np.in1d(np.ravel_multi_index(a.T,d), np.ravel_multi_index(b.T,d)))[0]

Out[72]: array([2], dtype=int64)

Note: I learned this trick a long time ago from @Divakar . so, credit should go to him.

2 Comments

this is amazing
Amazing indeed. It is not a complete solution to the general problem, as it fails if the arrays do not contain integers. Ehsan's solution does work with non-integer dtypes.
1

Try:

a = np.array([[1, 3], [2, 5], [1, 2], [2, 1], [1,6]])
b = np.array([[3, 5], [1, 2]])
check = any(map(lambda x: x in b, a))

Explanation:

  1. lambda is a key word to create a function. In this case:
    lambda x: x in b
    
    it represents a function that takes an x and returns if x is in array b
  2. map is a built-in function that takes a function as a first argument, and an iterable as a second argument. what it does is apply the first argument (the function) to every item in the iterable (the second argument) and return an iterable with these values. In this case:
    map(lambda x: x in b, a)
    
    it returns an iterable of True and False depending the result of applying the function throw the elements.
  3. Finally, any its another build-in function that takes and iterable of True's and False's and returns True if any item on the iterable is True

EDIT:

You can also do it using list comprehension (as someone write it down in comments):

a = np.array([[1, 3], [2, 5], [1, 2], [2, 1], [1,6]])
b = np.array([[3, 5], [1, 2]])
check = any(x in b for x in a)

It is exactly the same and even more legible.

4 Comments

any(x in b for x in a) is more Pythonic, though both will work.
Ohhh, you are right hahah, didn't think of that, thanks, i will added to the answer too
Your method is doing the comparison in a Python loop, which will be significantly slower than doing it in native NumPy. See the other answer for a NumPy solution.
as a ~~java~~ kotlin developer being asked to write some python this is exactly the answer I was looking for. Thank you.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.