Porównywanie dwóch tablic NumPy dla równości, pod względem elementów

252

Jaki jest najprostszy sposób porównania dwóch tablic NumPy dla równości (gdzie równość jest zdefiniowana jako: A = B iff dla wszystkich wskaźników i:) A[i] == B[i]?

Proste użycie ==daje mi tablicę boolowską:

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

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

Czy muszę andelementów tej tablicy, aby ustalić, czy tablice są równe, czy też istnieje prostszy sposób na porównanie?

clstaudt
źródło

Odpowiedzi:

380
(A==B).all()

sprawdź, czy wszystkie wartości tablicy (A == B) są prawdziwe.

Uwaga: być może chcesz również przetestować kształt A i B, na przykład A.shape == B.shape

Przypadki specjalne i alternatywy (z odpowiedzi dbaupp i komentarza yoavram)

Należy zauważyć że:

  • to rozwiązanie może mieć dziwne zachowanie w konkretnym przypadku: jeśli jeden Alub Bjest pusty, a drugi zawiera pojedynczy element, wówczas zwraca True. Z jakiegoś powodu porównanie A==Bzwraca pustą tablicę, do której allzwraca operator True.
  • Innym ryzykiem jest sytuacja Ai Bnie mają ten sam kształt i nie są broadcastable, to podejście zgłosi błąd.

Podsumowując, jeśli masz wątpliwości Ai Bkształtujesz lub po prostu chcesz być bezpieczny: skorzystaj z jednej ze specjalistycznych funkcji:

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_
źródło
26
Prawie zawsze chcesz np.array_equalIME. (A==B).all()ulegnie awarii, jeśli A i B mają różne długości . Począwszy od numpy 1.10, == podnosi ostrzeżenie o rezygnacji w tym przypadku .
Wilfred Hughes
Masz dobrą rację, ale w przypadku, gdy mam wątpliwości co do kształtu, zwykle wolę bezpośrednio przetestować go przed wartością. Zatem błąd wyraźnie dotyczy kształtów, które mają zupełnie inne znaczenie niż inne wartości. Ale to prawdopodobnie zależy od każdego przypadku użycia
Juh_
2
innym ryzykiem jest to, że tablice zawierają nan. W takim przypadku otrzymasz False, ponieważ nan! = Nan
Vincenzooo
1
Warto to podkreślić. Myślę jednak, że jest to logiczne, ponieważ nan!=nanimplikuje to array(nan)!=array(nan).
Juh_
Nie rozumiem tego zachowania: 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 jest macierzą jednolitą, więc H x H.T.conjjest macierzą tożsamości. Ale np.array_equalzwraca False
Dex
91

(A==B).all()Rozwiązanie jest bardzo schludny, ale istnieją pewne wbudowane funkcje dla tego zadania. Mianowicie array_equal, allclosei array_equiv.

(Chociaż niektóre szybkie testy timeitwydają się wskazywać, że (A==B).all()metoda jest najszybsza, co jest nieco dziwne, biorąc pod uwagę, że musi ona przydzielić całą nową tablicę.)

huon
źródło
15
masz rację, ale jeśli jedna z porównywanych tablic jest pusta, otrzymasz błędną odpowiedź (A==B).all(). Na przykład spróbuj (np.array([1])==np.array([])).all()Truenp.array_equal(np.array([1]), np.array([]))False
:,
1
Właśnie odkryłem tę różnicę wydajności. To dziwne, ponieważ jeśli masz 2 tablice, które są zupełnie inne, (a==b).all()wciąż jest szybsze niż np.array_equal(a, b)(które mogły po prostu sprawdzić pojedynczy element i wyjść).
Aidan Kane
np.array_equaldziała również z lists of arraysi dicts of arrays. Może to być przyczyną wolniejszej pracy.
Bernhard
Wielkie dzięki za funkcję allclose, właśnie tego potrzebowałem do obliczeń numerycznych . Porównuje równość wektorów w ramach tolerancji . :)
loved.by.Jesus
Zauważ, że np.array_equiv([1,1,1], 1) is True. Wynika to z faktu, że: Zgodny z kształtem oznacza, że ​​mają albo ten sam kształt, albo jedna tablica wejściowa może być rozgłaszana, aby utworzyć ten sam kształt co drugi.
EliadL
13

Zmierzmy wydajność za pomocą następującego fragmentu kodu.

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)

Wynik

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

Zgodnie z powyższymi wynikami metody numpy wydają się być szybsze niż połączenie operatora == i metody all () , a przez porównanie metod numpy najszybszą wydaje się metoda numpy.array_equal .

boj
źródło
4
Należy użyć większego rozmiaru tablicy, którego kompilacja zajmuje co najmniej sekundę, aby zwiększyć dokładność eksperymentu.
Vikhyat Agarwal
Czy to się powiela również po zmianie kolejności porównania? lub ponownie za każdym razem losowo A i B? Różnicę tę można również wytłumaczyć buforowaniem pamięci komórek A i B.
Lub Groman
3
Nie ma znaczącej różnicy między tymi czasami.
Do 마 SE
13

Jeśli chcesz sprawdzić, czy dwie tablice mają takie same shapeORAZ elementspowinieneś użyć, np.array_equalponieważ jest to metoda zalecana w dokumentacji.

Pod względem wydajności nie oczekuj, że jakakolwiek kontrola równości pokona kolejną, ponieważ nie ma wiele miejsca na optymalizację comparing two elements. Na wszelki wypadek wciąż przeprowadzałem testy.

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

Tak prawie równe, nie trzeba mówić o prędkości.

Że (A==B).all()zachowuje się dość dużo jak poniższym fragmencie kodu:

x = [1,2,3]
y = [1,2,3]
print all([x[i]==y[i] for i in range(len(x))])
> True
użytkownik1767754
źródło
5

Zwykle w dwóch tablicach występują niewielkie błędy numeryczne,

Możesz użyć numpy.allclose(A,B)zamiast (A==B).all(). Zwraca bool Prawda / Fałsz

R Zhang
źródło
0

Teraz użyj np.array_equal. Z dokumentacji:

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
źródło