Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using numpy isin element-wise between 2D and 1D arrays

I have quite a simple scenario where I'd like to test whether both elements of a two-dimensional array are (separately) members of a larger array - for example:

full_array = np.array(['A','B','C','D','E','F'])
sub_arrays = np.array([['A','C','F'],
                       ['B','C','E']])
np.isin(full_array, sub_arrays)

This gives me a single dimension output:

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

showing whether elements of full_array are present in either of the two sub-arrays. I'd like instead a two-dimensional array showing the same thing for each of the two elements in sub_arrays - so:

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

Hope that makes sense and any help gratefully received.

like image 800
Chris J Harris Avatar asked Dec 05 '18 11:12

Chris J Harris


People also ask

How do you add a 1D array to 2D array NumPy?

Use reshape() Function to Transform 1d Array to 2d Array The number of components within every dimension defines the form of the array. We may add or delete parameters or adjust the number of items within every dimension by using reshaping. To modify the layout of a NumPy ndarray, we will be using the reshape() method.

What is NumPy ISIN?

numpy.lib.arraysetops. Module with a number of other functions for performing set operations on arrays. Notes. isin is an element-wise function version of the python keyword in. isin(a, b) is roughly equivalent to np.

How do you compare elements of two NumPy arrays?

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 you find the common values between two arrays in NumPy?

In NumPy, we can find common values between two arrays with the help intersect1d(). It will take parameter two arrays and it will return an array in which all the common elements will appear.


1 Answers

Broadcasting based one

A simple one would be with broadcasting after extending one of the arrays and then any-reduction along the respective axis -

In [140]: (full_array==sub_arrays[...,None]).any(axis=1)
Out[140]: 
array([[ True, False,  True, False, False,  True],
       [False,  True,  True, False,  True, False]])

With searchsorted

Specific case #1

With full_array being sorted and all elements from sub_arrays present at least somewhere in full_array, we can also use np.searchsorted -

idx = np.searchsorted(full_array, sub_arrays)
out = np.zeros((sub_arrays.shape[0],len(full_array)),dtype=bool)
np.put_along_axis(out, idx, 1, axis=1)

Specific case #2

With full_array being sorted and if not all elements from sub_arrays are guaranteed to be present at least somewhere in full_array, we need one extra step -

idx = np.searchsorted(full_array, sub_arrays)
idx[idx==len(full_array)] = 0
out = np.zeros((sub_arrays.shape[0],len(full_array)),dtype=bool)
np.put_along_axis(out, idx, full_array[idx] == sub_arrays, axis=1)

Generic case

For the truly generic case of full_array not necessarily being sorted, we need to use sorter arg with searchsorted -

def isin2D(full_array, sub_arrays):
    out = np.zeros((sub_arrays.shape[0],len(full_array)),dtype=bool)
    sidx = full_array.argsort()
    idx = np.searchsorted(full_array, sub_arrays, sorter=sidx)
    idx[idx==len(full_array)] = 0
    idx0 = sidx[idx]
    np.put_along_axis(out, idx0, full_array[idx0] == sub_arrays, axis=1)
    return out

Sample run -

In [214]: full_array
Out[214]: array(['E', 'F', 'A', 'B', 'D', 'C'], dtype='|S1')

In [215]: sub_arrays
Out[215]: 
array([['Z', 'C', 'F'],
       ['B', 'C', 'E']], dtype='|S1')

In [216]: isin2D(full_array, sub_arrays)
Out[216]: 
array([[False,  True, False, False, False,  True],
       [ True, False, False,  True, False,  True]])
like image 84
Divakar Avatar answered Oct 25 '22 00:10

Divakar