Comparaison de deux tableaux NumPy pour l'égalité, par élément

254

Quelle est la manière la plus simple de comparer deux tableaux NumPy pour l'égalité (où l'égalité est définie comme: A = B ssi pour tous les indices i:) A[i] == B[i]?

Utiliser simplement ==me donne un tableau booléen:

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

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

Dois-je utiliser andles éléments de ce tableau pour déterminer si les tableaux sont égaux, ou existe-t-il un moyen plus simple de comparer?

clstaudt
la source

Réponses:

382
(A==B).all()

tester si toutes les valeurs du tableau (A == B) sont vraies.

Remarque: vous souhaitez peut-être également tester les formes A et B, telles que A.shape == B.shape

Cas spéciaux et alternatives (d'après la réponse de dbaupp et le commentaire de yoavram)

Il convient de noter que:

  • cette solution peut avoir un comportement étrange dans un cas particulier: si l'un Aou l' autre Best vide et que l'autre contient un seul élément, alors il revient True. Pour une raison quelconque, la comparaison A==Brenvoie un tableau vide, pour lequel l' allopérateur revient True.
  • Un autre risque est que si Aet Bn'ont pas la même forme et ne sont pas diffusables, cette approche soulèvera une erreur.

En conclusion, si vous avez un doute sur la forme Aet la Bforme ou si vous voulez simplement être en sécurité: utilisez l'une des fonctions spécialisées:

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_
la source
27
Vous voulez presque toujours np.array_equalIME. (A==B).all()se bloque si A et B ont des longueurs différentes . Depuis numpy 1.10, == déclenche un avertissement de dépréciation dans ce cas .
Wilfred Hughes
Vous avez un bon point, mais dans le cas où j'ai un doute sur la forme, je préfère généralement le tester directement, avant la valeur. Ensuite, l'erreur est clairement sur les formes qui ont une signification complètement différente que d'avoir des valeurs différentes. Mais cela dépend probablement de chaque cas d'utilisation
Juh_
2
un autre risque est que les tableaux contiennent des nan. Dans ce cas, vous obtiendrez Faux parce que nan! = Nan
Vincenzooo
1
C'est bon de le souligner. Cependant, je pense que c'est logique car cela nan!=nanimplique cela array(nan)!=array(nan).
Juh_
Je ne comprends pas ce comportement: 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 est une matrice unitaire, donc H x H.T.conjest une matrice d'identité. Mais np.array_equalrenvoie False
Dex
92

La (A==B).all()solution est très soignée, mais il existe des fonctions intégrées pour cette tâche. À savoir array_equal, allcloseet array_equiv.

(Bien que certains tests rapides avec timeitsemblent indiquer que la (A==B).all()méthode est la plus rapide, ce qui est un peu particulier, étant donné qu'elle doit allouer un tout nouveau tableau.)

huon
la source
16
vous avez raison, sauf que si l'un des tableaux comparés est vide, vous obtiendrez la mauvaise réponse (A==B).all(). Par exemple, essayez (np.array([1])==np.array([])).all()Truenp.array_equal(np.array([1]), np.array([]))False
:,
1
Je viens également de découvrir cette différence de performances. C'est étrange parce que si vous avez 2 tableaux complètement différents, (a==b).all()c'est encore plus rapide que np.array_equal(a, b)(qui aurait pu vérifier un seul élément et quitter).
Aidan Kane
np.array_equalfonctionne également avec lists of arrayset dicts of arrays. Cela pourrait être une raison pour une performance plus lente.
Bernhard
Merci beaucoup pour la fonction allclose, c'est ce dont j'avais besoin pour les calculs numériques . Il compare l'égalité des vecteurs dans une tolérance . :)
loves.by.Jesus
Notez cela np.array_equiv([1,1,1], 1) is True. En effet, la cohérence des formes signifie qu'elles sont soit de la même forme, soit qu'un tableau d'entrée peut être diffusé pour créer la même forme que l'autre.
EliadL
13

Mesurons les performances en utilisant le morceau de code suivant.

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)

Production

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

Selon les résultats ci-dessus, les méthodes numpy semblent être plus rapides que la combinaison de l' opérateur == et de la méthode all () et en comparant les méthodes numpy, la plus rapide semble être la méthode numpy.array_equal .

trouille
la source
5
Vous devez utiliser une taille de tableau plus grande qui prend au moins une seconde à compiler pour augmenter la précision de l'expérience.
Vikhyat Agarwal
Cela se reproduit-il également lorsque l'ordre de comparaison est modifié? ou réinitialisant A et B au hasard à chaque fois? Cette différence pourrait également s'expliquer par la mise en cache de la mémoire des cellules A et B.
Ou Groman
4
Il n'y a pas de différence significative entre ces horaires.
Au 마 SE
13

Si vous voulez vérifier si deux tableaux ont le même shapeET elementsvous devez utiliser np.array_equalcar c'est la méthode recommandée dans la documentation.

En termes de performances, ne vous attendez pas à ce qu'un contrôle d'égalité en batte un autre, car il n'y a pas beaucoup de place à optimiser comparing two elements. Juste pour le plaisir, j'ai quand même fait des tests.

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

Donc à peu près égal, pas besoin de parler de vitesse.

Le (A==B).all()se comporte à peu près comme l'extrait de code suivant:

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

Habituellement, deux tableaux auront quelques petites erreurs numériques,

Vous pouvez utiliser numpy.allclose(A,B), au lieu de (A==B).all(). Cela renvoie un bool True / False

R Zhang
la source
0

Maintenant, utilisez np.array_equal. De la documentation:

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
la source