Comparando duas matrizes NumPy para igualdade, em termos de elementos


252

Qual é a maneira mais simples de comparar duas matrizes NumPy para igualdade (onde igualdade é definida como: A = B iff para todos os índices i:) A[i] == B[i]?

Simplesmente usar ==me fornece uma matriz booleana:

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

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

Preciso anddos elementos dessa matriz para determinar se as matrizes são iguais ou se há uma maneira mais simples de comparar?

Respostas:


379
(A==B).all()

teste se todos os valores da matriz (A == B) são True.

Nota: talvez você também queira testar as formas A e B, como A.shape == B.shape

Casos e alternativas especiais (da resposta do dbaupp e do comentário do yoavram)

Note-se que:

  • Essa solução pode ter um comportamento estranho em um caso específico: se um Aou Bestá vazio e o outro contém um único elemento, então ele retorna True. Por algum motivo, a comparação A==Bretorna uma matriz vazia, para a qual o alloperador retorna True.
  • Outro risco é se Ae Bnão têm a mesma forma e não são irradiável, então esta abordagem irá gerar um erro.

Concluindo, se você tiver alguma dúvida Ae Bforme ou simplesmente deseja estar seguro: use uma das funções 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

26
Você quase sempre quer np.array_equalIME. (A==B).all()irá falhar se A e B têm diferentes comprimentos . A partir do numpy 1.10, == gera um aviso de descontinuação neste caso .
Wilfred Hughes

Você tem um bom argumento, mas no caso de eu ter uma dúvida sobre a forma, geralmente prefiro testá-lo diretamente, antes do valor. Então, o erro está claramente nas formas que têm um significado completamente diferente do que ter valores diferentes. Mas isso provavelmente depende de cada caso de uso
Juh_ 06/08/19

2
outro risco é se as matrizes contiverem nan. Nesse caso, você obterá False porque nan! = Nan #
Vincenzooo

1
É bom ressaltar. No entanto, acho que isso é lógico, porque nan!=nanimplica isso array(nan)!=array(nan).
Juh_

Eu não entendo esse comportamento: 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 é uma matriz unitária, então H x H.T.conjé uma matriz de identidade. Mas np.array_equalretorna False
Dex

91

A (A==B).all()solução é muito elegante, mas existem algumas funções internas para esta tarefa. Ou seja array_equal, allclosee array_equiv.

(Embora alguns testes rápidos timeitpareçam indicar que o (A==B).all()método é o mais rápido, o que é um pouco peculiar, já que ele precisa alocar uma matriz totalmente nova).


15
você está certo, exceto que se uma das matrizes comparadas estiver vazia, você receberá a resposta errada (A==B).all(). Por exemplo, tente (np.array([1])==np.array([])).all()Truenp.array_equal(np.array([1]), np.array([]))False
:,

1
Acabei de descobrir essa diferença de desempenho também. É estranho, porque se você tiver duas matrizes completamente diferentes, (a==b).all()ainda será mais rápido do que np.array_equal(a, b)(o que poderia ter verificado apenas um elemento e ter sido encerrado).
Aidan Kane

np.array_equaltambém trabalha com lists of arrayse dicts of arrays. Isso pode ser um motivo para um desempenho mais lento.
Bernhard

Muito obrigado pela função allclose, era disso que eu precisava para cálculos numéricos . Ele compara a igualdade de vetores dentro de uma tolerância . :)
loved.by.Jesus

Note isso np.array_equiv([1,1,1], 1) is True. Isso ocorre porque: Forma consistente significa que eles têm a mesma forma ou uma matriz de entrada pode ser transmitida para criar a mesma forma que a outra.
EliadL

13

Vamos medir o desempenho usando o seguinte trecho de 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)

Resultado

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

De acordo com os resultados acima, os métodos numpy parecem ser mais rápidos que a combinação do operador == e o método all () e, comparando os métodos numpy, o mais rápido parece ser o método numpy.array_equal .


4
Você deve usar um tamanho de matriz maior que leve pelo menos um segundo para compilar para aumentar a precisão do experimento.
Vikhyat Agarwal

Isso também se reproduz quando a ordem de comparação é alterada? ou reiniciar A e B para aleatoriamente cada vez? Essa diferença também pode ser explicada pelo armazenamento em cache de memória das células A e B.
Ou Groman

3
Não há diferença significativa entre esses horários.
Para SE

13

Se você deseja verificar se duas matrizes têm o mesmo shapeAND, elementsvocê deve usá- np.array_equallo, pois é o método recomendado na documentação.

Em termos de desempenho, não espere que nenhuma verificação de igualdade supere outra, pois não há muito espaço para otimizar comparing two elements. Só por uma questão, eu ainda fiz alguns testes.

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

Tão praticamente igual, não há necessidade de falar sobre a velocidade.

O (A==B).all()comportamento se comporta praticamente como o seguinte trecho de código:

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

5

Normalmente, duas matrizes apresentam pequenos erros numéricos,

Você pode usar numpy.allclose(A,B), em vez de (A==B).all(). Isso retorna um booleano Verdadeiro / Falso


0

Agora use np.array_equal. Da documentação:

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
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.