Comparando dos matrices NumPy para igualdad, en cuanto a elementos

252

¿Cuál es la forma más simple de comparar dos matrices NumPy para la igualdad (donde la igualdad se define como: A = B iff para todos los índices i:) A[i] == B[i]?

Simplemente usando ==me da una matriz booleana:

 >>> numpy.array([1,1,1]) == numpy.array([1,1,1])

array([ True,  True,  True], dtype=bool)

¿Tengo que ver andlos elementos de esta matriz para determinar si las matrices son iguales o hay una forma más sencilla de comparar?

clstaudt
fuente

Respuestas:

380
(A==B).all()

pruebe si todos los valores de la matriz (A == B) son verdaderos.

Nota: tal vez también desee probar las formas A y B, como A.shape == B.shape

Casos especiales y alternativas (de la respuesta de dbaupp y el comentario de yoavram)

Se debe notar que:

  • Esta solución puede tener un comportamiento extraño en un caso particular: si uno Ao Bestá vacío y el otro contiene un solo elemento, entonces regresa True. Por alguna razón, la comparación A==Bdevuelve una matriz vacía, para la cual el alloperador regresa True.
  • Otro riesgo es que si Ay Bno tienen la misma forma y no son broadcastable, a continuación, este enfoque generará un error.

En conclusión, si tiene dudas Ay Bformas o simplemente quiere estar seguro: use una de las funciones especializadas:

np.array_equal(A,B)  # test if same shape, same elements values
np.array_equiv(A,B)  # test if broadcastable shape, same elements values
np.allclose(A,B,...) # test if same shape, elements have close enough values
Juh_
fuente
26
Casi siempre quieres np.array_equalIME. (A==B).all()se bloqueará si A y B tienen longitudes diferentes . A partir de 1.10 numpy, == genera una advertencia de desaprobación en este caso .
Wilfred Hughes
Tienes un buen punto, pero en el caso de que tenga dudas sobre la forma, generalmente prefiero probarlo directamente, antes del valor. Entonces el error está claramente en las formas que tienen un significado completamente diferente de tener valores diferentes. Pero eso probablemente depende de cada caso de uso
Juh_
2
Otro riesgo es si las matrices contienen nan. En ese caso, obtendrá False porque nan! = Nan
Vincenzooo
1
Es bueno señalarlo. Sin embargo, creo que esto es lógico porque nan!=nanimplica eso array(nan)!=array(nan).
Juh_
No entiendo este comportamiento: import numpy as np H = 1/np.sqrt(2)*np.array([[1, 1], [1, -1]]) #hadamard matrix np.array_equal(H.dot(H.T.conj()), np.eye(len(H))) # checking if H is an unitary matrix or not H es una matriz unitaria, entonces H x H.T.conjes una matriz de identidad. Pero np.array_equalregresa False
Dex
91

La (A==B).all()solución es muy clara, pero hay algunas funciones integradas para esta tarea. A saber array_equal, allclosey array_equiv.

(Aunque, algunas pruebas rápidas timeitparecen indicar que el (A==B).all()método es el más rápido, lo cual es un poco peculiar, dado que tiene que asignar una matriz completamente nueva).

huon
fuente
15
tienes razón, excepto que si una de las matrices comparadas está vacía, obtendrás la respuesta incorrecta (A==B).all(). Por ejemplo, intente:, (np.array([1])==np.array([])).all()da True, mientras np.array_equal(np.array([1]), np.array([]))daFalse
yoavram
1
Acabo de descubrir esta diferencia de rendimiento también. Es extraño porque si tiene 2 matrices que son completamente diferentes, (a==b).all()aún es más rápido que np.array_equal(a, b)(lo que podría haber verificado un solo elemento y haber salido).
Aidan Kane
np.array_equalTambién trabaja con lists of arraysy dicts of arrays. Esto podría ser una razón para un rendimiento más lento.
Bernhard
Muchas gracias por la función allclose, eso es lo que necesitaba para los cálculos numéricos . Compara la igualdad de vectores dentro de una tolerancia . :)
loved.by.Jesus
Tenga en cuenta que np.array_equiv([1,1,1], 1) is True. Esto se debe a que: Forma consistente significa que tienen la misma forma o que se puede emitir una matriz de entrada para crear la misma forma que la otra.
EliadL
13

Midamos el rendimiento utilizando el siguiente código.

import numpy as np
import time

exec_time0 = []
exec_time1 = []
exec_time2 = []

sizeOfArray = 5000
numOfIterations = 200

for i in xrange(numOfIterations):

    A = np.random.randint(0,255,(sizeOfArray,sizeOfArray))
    B = np.random.randint(0,255,(sizeOfArray,sizeOfArray))

    a = time.clock() 
    res = (A==B).all()
    b = time.clock()
    exec_time0.append( b - a )

    a = time.clock() 
    res = np.array_equal(A,B)
    b = time.clock()
    exec_time1.append( b - a )

    a = time.clock() 
    res = np.array_equiv(A,B)
    b = time.clock()
    exec_time2.append( b - a )

print 'Method: (A==B).all(),       ', np.mean(exec_time0)
print 'Method: np.array_equal(A,B),', np.mean(exec_time1)
print 'Method: np.array_equiv(A,B),', np.mean(exec_time2)

Salida

Method: (A==B).all(),        0.03031857
Method: np.array_equal(A,B), 0.030025185
Method: np.array_equiv(A,B), 0.030141515

De acuerdo con los resultados anteriores, los métodos numpy parecen ser más rápidos que la combinación del operador == y el método all () y al comparar los métodos numpy, el más rápido parece ser el método numpy.array_equal .

canguelo
fuente
44
Debe usar un tamaño de matriz más grande que tome al menos un segundo para compilar para aumentar la precisión del experimento.
Vikhyat Agarwal
¿Esto también se reproduce cuando se cambia el orden de comparación? o reiniciar A y B al azar cada vez? Esta diferencia también podría explicarse por el almacenamiento en memoria caché de las células A y B.
O Groman
3
No hay una diferencia significativa entre estos tiempos.
Hasta 마 SE
13

Si desea verificar si dos matrices tienen el mismo shapeY elementsdebe usar, np.array_equalya que es el método recomendado en la documentación.

En cuanto al rendimiento, no espere que cualquier verificación de igualdad supere a otra, ya que no hay mucho espacio para optimizar comparing two elements. Solo por el bien, todavía hice algunas pruebas.

import numpy as np
import timeit

A = np.zeros((300, 300, 3))
B = np.zeros((300, 300, 3))
C = np.ones((300, 300, 3))

timeit.timeit(stmt='(A==B).all()', setup='from __main__ import A, B', number=10**5)
timeit.timeit(stmt='np.array_equal(A, B)', setup='from __main__ import A, B, np', number=10**5)
timeit.timeit(stmt='np.array_equiv(A, B)', setup='from __main__ import A, B, np', number=10**5)
> 51.5094
> 52.555
> 52.761

Casi igual, no hay necesidad de hablar sobre la velocidad.

El se (A==B).all()comporta más o menos como el siguiente fragmento de código:

x = [1,2,3]
y = [1,2,3]
print all([x[i]==y[i] for i in range(len(x))])
> True
usuario1767754
fuente
5

Por lo general, dos matrices tendrán algunos pequeños errores numéricos,

Puedes usar numpy.allclose(A,B), en lugar de (A==B).all(). Esto devuelve un bool verdadero / falso

R Zhang
fuente
0

Ahora usa np.array_equal. De la documentación:

np.array_equal([1, 2], [1, 2])
True
np.array_equal(np.array([1, 2]), np.array([1, 2]))
True
np.array_equal([1, 2], [1, 2, 3])
False
np.array_equal([1, 2], [1, 4])
False
keramat
fuente