Пересечение строк в 2 массивах разного размера numpy - PullRequest
0 голосов
/ 11 июля 2020

Предположим, у меня есть 2 numpy массивов:

arr1 = np.array([
       [1, 2, 3, 4],
       [2, 3, 1, 4],
       [2, 4, 1, 5],
       ...)

arr2 = np.array([
       [2, 4, 1, 5],
       [2, 1, 3, 5],
       [1, 2, 3, 4],
       ...)

Я хотел бы получить пересечение строк для arr1 и arr2. Я пробовал:

intersect = np.intersect1d(arr1, arr2)

, и он возвращает

array([1, 2, 3, 4, 5])

, что означает поэлементное пересечение. Я бы хотел выполнить sh это построчно. Он должен вернуться как:

array(
      [2, 4, 1, 5],
      [1, 2, 3, 5])

1 Ответ

2 голосов
/ 11 июля 2020
In [3]: arr1 = np.array([ 
   ...:        [1, 2, 3, 4], 
   ...:        [2, 3, 1, 4], 
   ...:        [2, 4, 1, 5], 
   ...:        ]) 
   ...:  
   ...: arr2 = np.array([ 
   ...:        [2, 4, 1, 5], 
   ...:        [2, 1, 3, 5], 
   ...:        [1, 2, 3, 4], 
   ...:        ]) 
                                                                                        

транслируемое равенство, за которым следует соответствующее сочетание all и any:

In [8]: (arr1[:,None,:]==arr2[None,:,:]).shape                                                       
Out[8]: (3, 3, 4)
In [9]: (arr1[:,None,:]==arr2[None,:,:]).all(axis=2)                                                 
Out[9]: 
array([[False, False,  True],
       [False, False, False],
       [ True, False, False]])
In [10]: (arr1[:,None,:]==arr2[None,:,:]).all(axis=2).any(axis=0)                                    
Out[10]: array([ True, False,  True])

In [12]: arr1[_]                                                                                     
Out[12]: 
array([[1, 2, 3, 4],
       [2, 4, 1, 5]])

С наборами

In [19]: set([tuple(row) for row in arr1])                                                           
Out[19]: {(1, 2, 3, 4), (2, 3, 1, 4), (2, 4, 1, 5)}
In [20]: set([tuple(row) for row in arr2])                                                           
Out[20]: {(1, 2, 3, 4), (2, 1, 3, 5), (2, 4, 1, 5)}
In [21]: _19.intersection(_20)                                                                       
Out[21]: {(1, 2, 3, 4), (2, 4, 1, 5)}

===

Если я расширю arr2 до 4 строк:

...: arr2 = np.array([ 
...:        [2, 4, 1, 5], 
...:        [2, 1, 3, 5], 
...:        [1, 2, 3, 4], 
...:        [1, 1, 1, 1], 
...:        ]) 

In [34]: (arr1[:,None,:]==arr2[None,:,:]).all(axis=2).any(axis=0)                                    
Out[34]: array([ True, False,  True, False])

any на 0 создаст 4-элементный массив, который должен использоваться для индексации arr2 (а не arr1, как я изначально ):

In [35]: arr2[_]                                                                                     
Out[35]: 
array([[2, 4, 1, 5],
       [1, 2, 3, 4]])

Или any по другой оси:

In [36]: (arr1[:,None,:]==arr2[None,:,:]).all(axis=2).any(axis=1)                                    
Out[36]: array([ True, False,  True])
In [37]: arr1[_]                                                                                     
Out[37]: 
array([[1, 2, 3, 4],
       [2, 4, 1, 5]])

all создает (в данном случае) массив (3,4):

In [38]: (arr1[:,None,:]==arr2[None,:,:]).all(axis=2)                                                
Out[38]: 
array([[False, False,  True, False],
       [False, False, False, False],
       [ True, False, False, False]])

any может уменьшать строки или столбцы.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...