Vergleich zweier NumPy-Arrays auf Gleichheit, elementweise

252

Was ist der einfachste Weg, um zwei NumPy-Arrays auf Gleichheit zu vergleichen (wobei Gleichheit definiert ist als: A = B iff für alle Indizes i :) A[i] == B[i]?

Durch einfaches Verwenden ==erhalte ich ein boolesches Array:

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

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

Muss ich anddie Elemente dieses Arrays verwenden, um festzustellen, ob die Arrays gleich sind, oder gibt es eine einfachere Möglichkeit zum Vergleichen?

clstaudt
quelle

Antworten:

379
(A==B).all()

Testen Sie, ob alle Werte des Arrays (A == B) True sind.

Hinweis: Vielleicht möchten Sie auch die A- und B-Form testen, z A.shape == B.shape

Sonderfälle und Alternativen (aus der Antwort von dbaupp und dem Kommentar von yoavram)

Es sollte erwähnt werden, dass:

  • Diese Lösung kann in einem bestimmten Fall ein seltsames Verhalten haben: Wenn entweder Aoder Bleer ist und das andere ein einzelnes Element enthält, wird es zurückgegeben True. Aus irgendeinem Grund gibt der Vergleich A==Bein leeres Array zurück, für das der allOperator zurückgibt True.
  • Ein weiteres Risiko ist , wenn Aund Bnicht die gleiche Form hat und nicht sandte, dann wird dieser Ansatz einen Fehler erhöhen.

Zum Schluss, wenn Sie einen Zweifel haben Aund Bwollen Form oder einfach nur um sicher zu sein: Verwendung einer der spezialisierten Funktionen:

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_
quelle
25
Sie wollen fast immer np.array_equalIME. (A==B).all()wird abstürzen , wenn A und B unterschiedliche Längen aufweisen . Ab Nummer 1.10 löst == in diesem Fall eine Verfallswarnung aus .
Wilfred Hughes
Sie haben einen guten Punkt, aber falls ich Zweifel an der Form habe, ziehe ich es normalerweise vor, sie direkt vor dem Wert zu testen. Dann liegt der Fehler eindeutig bei den Formen, die eine völlig andere Bedeutung haben als andere Werte. Aber das hängt wahrscheinlich von jedem Anwendungsfall ab
Juh_
2
Ein weiteres Risiko besteht darin, dass die Arrays Nan enthalten. In diesem Fall erhalten Sie False, weil nan! = Nan
Vincenzooo
1
Gut darauf hinzuweisen. Ich halte dies jedoch für logisch, da dies nan!=nanimpliziert array(nan)!=array(nan).
Juh_
Ich verstehe dieses Verhalten nicht: 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 ist eine einheitliche Matrix, also ist H x H.T.conjeine Identitätsmatrix. Aber np.array_equalkehrt zurück False
Dex
91

Die (A==B).all()Lösung ist sehr ordentlich, aber es gibt einige integrierte Funktionen für diese Aufgabe. Nämlich array_equal, allcloseund array_equiv.

(Obwohl einige schnelle Tests mit timeitzu zeigen scheinen, dass die (A==B).all()Methode die schnellste ist, was etwas eigenartig ist, da sie ein ganz neues Array zuweisen muss.)

huon
quelle
15
Sie haben Recht, außer dass Sie die falsche Antwort erhalten, wenn eines der verglichenen Arrays leer ist (A==B).all(). Versuchen (np.array([1])==np.array([])).all()Sie zum Beispiel : , es gibt True, während np.array_equal(np.array([1]), np.array([]))gibtFalse
Yoavram
1
Ich habe gerade auch diesen Leistungsunterschied entdeckt. Es ist seltsam, denn wenn Sie 2 Arrays haben, die völlig unterschiedlich sind, (a==b).all()ist dies immer noch schneller als np.array_equal(a, b)(was nur ein einzelnes Element hätte überprüfen und beenden können).
Aidan Kane
np.array_equalfunktioniert auch mit lists of arraysund dicts of arrays. Dies könnte ein Grund für eine langsamere Leistung sein.
Bernhard
Vielen Dank für die Funktion allclose, die ich für numerische Berechnungen brauchte . Es vergleicht die Gleichheit von Vektoren innerhalb einer Toleranz . :)
geliebt.von.Jesus
Beachten Sie das np.array_equiv([1,1,1], 1) is True. Dies liegt daran, dass: Formkonsistent bedeutet, dass sie entweder dieselbe Form haben oder dass ein Eingabearray gesendet werden kann, um dieselbe Form wie das andere zu erstellen.
EliadL
13

Lassen Sie uns die Leistung mithilfe des folgenden Codes messen.

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)

Ausgabe

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

Gemäß den obigen Ergebnissen scheinen die numpy-Methoden schneller zu sein als die Kombination des == -Operators und der all () -Methode, und durch Vergleichen der numpy-Methoden scheint die numpy.array_equal- Methode die schnellste zu sein .

Funk
quelle
4
Sie sollten ein größeres Array verwenden, dessen Kompilierung mindestens eine Sekunde dauert, um die Experimentgenauigkeit zu erhöhen.
Vikhyat Agarwal
Wird dies auch reproduziert, wenn die Vergleichsreihenfolge geändert wird? oder A und B jedes Mal wieder zufällig aktivieren? Dieser Unterschied könnte auch durch das Speicher-Caching von A- und B-Zellen erklärt werden.
Oder Groman
3
Es gibt keinen bedeutenden Unterschied zwischen diesen Timings.
Bis
13

Wenn Sie überprüfen möchten, ob zwei Arrays dasselbe shapeUND haben elements, sollten Sie diese verwenden, np.array_equalda dies die in der Dokumentation empfohlene Methode ist.

In Bezug auf die Leistung erwarten Sie nicht, dass eine Gleichstellungsprüfung eine andere schlägt, da nicht viel Raum für Optimierungen besteht comparing two elements. Nur um der Sache willen habe ich noch einige Tests gemacht.

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

So ziemlich gleich, dass man nicht über die Geschwindigkeit sprechen muss.

Das (A==B).all()verhält sich so ziemlich wie das folgende Code-Snippet:

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

Normalerweise weisen zwei Arrays einige kleine numerische Fehler auf.

Sie können numpy.allclose(A,B)anstelle von verwenden (A==B).all(). Dies gibt ein bool True / False zurück

R Zhang
quelle
0

Jetzt verwenden np.array_equal. Aus der Dokumentation:

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
quelle