¿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)