Compruebe si hay filas idénticas en diferentes matrices numpy

¿Cómo obtengo una comparación por filas entre dos matrices, en el resultado de una matriz verdadera / falsa por filas?

Datos dados:

a = np.array([[1,0],[2,0],[3,1],[4,2]]) b = np.array([[1,0],[2,0],[4,2]]) 

Resultado paso 1:

 c = np.array([True, True,False,True]) 

Resultado final:

 a = a[c] 

Entonces, ¿cómo puedo obtener la matriz c

PD: En este ejemplo, las matrices a y b están ordenadas, proporcione también información si en su solución es importante que las matrices estén ordenadas

Aquí hay una solución vectorizada:

 res = (a[:, None] == b).all(-1).any(-1) print(res) array([ True, True, False, True]) 

Tenga en cuenta que a[:, None] == b compara cada fila de a con b elemento. Luego, usamos all + any para deducir si hay alguna fila que sea True para cada sub-matriz:

 print(a[:, None] == b) [[[ True True] [False True] [False False]] [[False True] [ True True] [False False]] [[False False] [False False] [False False]] [[False False] [False False] [ True True]]] 

puede usar numpy con apply_along_axis (tipo de iteración en un eje específico mientras axis = 0 iterar en cada celda, axis = 1 iterar en cada fila, axis = 2 en la matriz y así sucesivamente

 import numpy as np a = np.array([[1,0],[2,0],[3,1],[4,2]]) b = np.array([[1,0],[2,0],[4,2]]) c = np.apply_along_axis(lambda x,y: x in y, 1, a, b) 

Enfoque # 1

Podríamos usar una solución vectorizada basada en view .

 # https://stackoverflow.com/a/45313353/ @Divakar def view1D(a, b): # a, b are arrays a = np.ascontiguousarray(a) b = np.ascontiguousarray(b) void_dt = np.dtype((np.void, a.dtype.itemsize * a.shape[1])) return a.view(void_dt).ravel(), b.view(void_dt).ravel() A,B = view1D(a,b) out = np.isin(A,B) 

Ejecución de la muestra

 In [8]: a Out[8]: array([[1, 0], [2, 0], [3, 1], [4, 2]]) In [9]: b Out[9]: array([[1, 0], [2, 0], [4, 2]]) In [10]: A,B = view1D(a,b) In [11]: np.isin(A,B) Out[11]: array([ True, True, False, True]) 

Enfoque # 2

Alternativamente para el caso en el que todas las filas en b están en a y las filas están ordenadas lexicográficamente, usando las mismas views , pero con searchsorted

 out = np.zeros(len(A), dtype=bool) out[np.searchsorted(A,B)] = 1 

Si las filas no están necesariamente ordenadas lexicográficamente –

 sidx = A.argsort() out[sidx[np.searchsorted(A,B,sorter=sidx)]] = 1 

Puedes hacerlo como una lista comp a través de:

 c = np.array([row in b for row in a]) 

aunque este enfoque será más lento que un enfoque de números puros (si existe).

 a = np.array([[1,0],[2,0],[3,1],[4,2]]) b = np.array([[1,0],[2,0],[4,2]]) i = 0 j = 0 result = [] 

Podemos aprovechar el hecho de que están ordenados y hacerlo en O (n) tiempo. Usando dos punteros, simplemente avanzamos el puntero que se ha atrasado:

 while i < len(a) and j < len(b): if tuple(a[i])== tuple(b[j]): result.append(True) i += 1 j += 1 # get rid of this depending on how you want to handle duplicates elif tuple(a[i]) > tuple(b[j]): j += 1 else: result.append(False) i += 1 

Pad con falso si termina temprano.

 if len(result) < len(a): result.extend([False] * (len(a) - len(result))) print(result) # [True, True, False, True] 

Esta respuesta está adaptada de ¿ Mejor manera de encontrar coincidencias en dos listas ordenadas que usar para bucles? (Java)