Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to match pairs of values contained in two numpy arrays

I have two sets of coordinates and want to find out which coordinates of the coo set are identical to any coordinate in the targets set. I want to know the indices in the coo set which means I'd like to get a list of indices or of bools.

import numpy as np

coo = np.array([[1,2],[1,6],[5,3],[3,6]]) # coordinates
targets = np.array([[5,3],[1,6]]) # coordinates of targets

print(np.isin(coo,targets))

[[ True False]
 [ True  True]
 [ True  True]
 [ True  True]]

The desired result would be one of the following two:

[False True True False] # bool list
[1,2] # list of concerning indices

My problem is, that ...

  • np.isin has no axis-attribute so that I could use axis=1.
  • even applying logical and to each row of the output would return True for the last element, which is wrong.

I am aware of loops and conditions but I am sure Python is equipped with ways for a more elegant solution.

like image 276
Hein Schnell Avatar asked Feb 22 '19 13:02

Hein Schnell


People also ask

How do I compare values in two NumPy arrays?

Method 1: We generally use the == operator to compare two NumPy arrays to generate a new array object. Call ndarray. all() with the new array object as ndarray to return True if the two NumPy arrays are equivalent.

How do you compare values between two arrays in Python?

The easiest way to compare two NumPy arrays is to: Create a comparison array by calling == between two arrays. Call . all() method for the result array object to check if the elements are True.

How do I link two NumPy arrays?

Use numpy.stack() function to join a sequence of arrays along a new axis. You pass a sequence of arrays that you want to join to the numpy. stack() function along with the axis. If the axis is not explicitly passed it is taken as zero.

How do you compare each element in a NumPy array?

To compare each element of a NumPy array arr against the scalar x using any of the greater (>), greater equal (>=), smaller (<), smaller equal (<=), or equal (==) operators, use the broadcasting feature with the array as one operand and the scalar as another operand.


1 Answers

This solution will scale worse for large arrays, for such cases the other proposed answers will perform better.


Here's one way taking advantage of broadcasting:

(coo[:,None] == targets).all(2).any(1)
# array([False,  True,  True, False])

Details

Check for every row in coo whether or not it matches another in target by direct comparisson having added a first axis to coo so it becomes broadcastable against targets:

(coo[:,None] == targets)

array([[[False, False],
        [ True, False]],

       [[False, False],
        [ True,  True]],

       [[ True,  True],
        [False, False]],

       [[False, False],
        [False,  True]]])

Then check which ndarrays along the second axis have all values to True:

(coo[:,None] == targets).all(2)

array([[False, False],
       [False,  True],
       [ True, False],
       [False, False]])

And finally use any to check which rows have at least one True.

like image 90
yatu Avatar answered Sep 24 '22 02:09

yatu