438 votes

Comparaison de l'égalité de deux tableaux numpy

Quelle est la façon la plus simple de comparer deux tableaux numpy pour l'égalité (où l'égalité est définie comme : A = B si pour tous les indices i : A[i] == B[i] ) ?

En utilisant simplement == me donne un tableau booléen :

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

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

Est-ce que je dois and les éléments de ce tableau pour déterminer si les tableaux sont égaux, ou existe-t-il un moyen plus simple de les comparer ?

640voto

Juh_ Points 1314
(A==B).all()

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

Modifier (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 ou l'autre des éléments suivants A ou B est vide et l'autre contient un seul élément, alors il retourne True . Pour une raison quelconque, la comparaison A==B renvoie un tableau vide, pour lequel le all L'opérateur retourne True .
  • Un autre risque est que A et B n'ont pas la même forme et ne sont pas diffusables, cette approche entraînera une erreur.

En conclusion, la solution que j'ai proposée est la solution standard, je pense, mais si vous avez un doute sur A et B ou simplement pour être sûr : 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

64 votes

Vous voulez presque toujours np.array_equal IME. (A==B).all() sera crash si A et B ont des longueurs différentes . A partir de numpy 1.10, \== soulève un avertissement de dépréciation dans ce cas. .

1 votes

Vous avez raison, mais dans le cas où j'ai un doute sur la forme, je préfère généralement la tester directement, avant la valeur. Alors 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

3 votes

un autre risque est que les tableaux contiennent des nan. Dans ce cas, vous obtiendrez False car nan != nan.

131voto

dbaupp Points 20762

Le site (A==B).all() est très soignée, mais il existe des fonctions intégrées pour cette tâche. Notamment array_equal , allclose et array_equiv .

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

21 votes

vous avez raison, sauf que si l'un des tableaux comparés est vide, vous obtiendrez la mauvaise réponse avec (A==B).all() . Par exemple, essayez : (np.array([1])==np.array([])).all() on obtient True alors que np.array_equal(np.array([1]), np.array([])) donne False

1 votes

Je viens aussi de découvrir cette différence de performance. C'est étrange parce que si vous avez 2 tableaux qui sont complètement différents (a==b).all() est toujours plus rapide que np.array_equal(a, b) (qui aurait pu se contenter de vérifier un seul élément et sortir).

1 votes

np.array_equal fonctionne également avec lists of arrays et dicts of arrays . Cela peut être la raison d'une performance plus lente.

22voto

user1767754 Points 460

Si vous voulez vérifier si deux tableaux ont le même shape ET elements vous devez utiliser np.array_equal car 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é soit plus performant qu'un autre, car il n'y a pas beaucoup de possibilités d'optimisation. comparing two elements . Juste pour le plaisir, j'ai quand même fait quelques 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 égaux, pas besoin de parler de la vitesse.

Le site (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

17voto

funk Points 24

Mesurons la performance 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)

Sortie

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

D'après les résultats ci-dessus, les méthodes numpy semblent être plus rapides que la combinaison des méthodes \== et l'opérateur tous() et en comparant les méthodes numpy le plus rapide l'un d'eux semble être le numpy.array_equal méthode.

9 votes

Pour augmenter la précision de l'expérience, vous devez utiliser une taille de tableau plus grande qui prend au moins une seconde à compiler.

0 votes

Cela se reproduit-il également lorsque l'ordre de comparaison est modifié ? ou lorsque A et B sont réinitialisés au hasard à chaque fois ? Cette différence pourrait également s'expliquer par la mise en mémoire des cellules A et B.

7 votes

Il n'y a pas de différence significative entre ces timings.

10voto

R Zhang Points 111

En général, deux tableaux présentent de petites erreurs numériques,

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

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X