Comparación de dos matrices numpy para el cumplimiento de dos condiciones
Considere dos matrices numpy que tienen la misma forma, A y B, compuestas por unos y ceros. Se muestra un pequeño ejemplo:
A = [[1 0 0 1] B = [[0 0 0 0]
[0 0 1 0] [0 0 0 0]
[0 0 0 0] [1 1 0 0]
[0 0 0 0] [0 0 1 0]
[0 0 1 1]] [0 1 0 1]]
Ahora quiero asignar valores a las dos variables booleanas test1 y test2 de la siguiente manera:
test1 : ¿Hay al menos una instancia en la que un 1 en una A
columna y un 1 en la MISMA B
columna tengan diferencias de fila de exactamente 1 o 2? Si es así, entonces prueba1 = Verdadero, de lo contrario Falso.
En el ejemplo anterior, la columna 0 de ambas matrices tiene unos que están separados por 2 filas, por lo que test1 = True. (También hay otras instancias en la columna 2, pero eso no importa, solo requerimos una instancia).
test2 : ¿Los valores 1 de A
y B
todos tienen direcciones de matriz diferentes? Si es así, entonces prueba2 = Verdadero, de lo contrario Falso.
En el ejemplo anterior, ambas matrices tienen [4,3] = 1
, entonces test2 = False.
Estoy luchando por encontrar una manera eficiente de hacer esto y agradecería alguna ayuda.
Respuestas
Aquí hay una forma sencilla de probar si dos matrices tienen una entrada con un elemento aparte en la misma columna (solo en una dirección):
(A[1:, :] * B[:-1, :]).any(axis=None)
Para que puedas hacer
test1 = (A[1:, :] * B[:-1, :] + A[:-1, :] * B[1:, :]).any(axis=None) or (A[2:, :] * B[:-2, :] + A[:-2, :] * B[2:, :]).any(axis=None)
La segunda prueba se puede realizar convirtiendo las ubicaciones en índices, apilándolos y utilizándolos np.unique
para contar el número de duplicados. Los duplicados solo pueden provenir del mismo índice en dos matrices, ya que una matriz nunca tendrá índices duplicados. Podemos acelerar aún más el cálculo usando en flatnonzero
lugar de nonzero
:
test2 = np.all(np.unique(np.concatenate((np.flatnonzero(A), np.flatnonzero(B))), return_counts=True)[1] == 1)
Una prueba más eficiente usaría np.intersect1d
de manera similar:
test2 = not np.intersect1d(np.flatnonzero(A), np.flatnonzero(B)).size
Puede usar masked_arrays y para la segunda tarea puede hacer:
A_m = np.ma.masked_equal(A, 0)
B_m = np.ma.masked_equal(B, 0)
test2 = np.any((A_m==B_m).compressed())
Y una forma ingenua de hacer la primera tarea es:
test1 = np.any((np.vstack((A_m[:-1],A_m[:-2],A_m[1:],A_m[2:]))==np.vstack((B_m[1:],B_m[2:],B_m[:-1],B_m[:-2]))).compressed())
salida:
True
True
Para Test2: puede verificar si encontraron índices similares encontrados para un valor de 1.
A = np.array([[1, 0, 0, 1],[0, 0, 1, 0],[0, 0, 0, 0],[0, 0, 0, 0],[0, 0, 1, 1]])
B = np.array([[0, 0, 0, 0],[0, 0, 0, 0],[1, 1, 0, 0],[0, 0, 1, 0],[0, 1, 0, 1]])
print(len(np.intersect1d(np.flatnonzero(A==1),np.flatnonzero(B==1)))>0))