Порівнюючи два масиви NumPy для рівності, по елементу


252

Який найпростіший спосіб порівняти два масиви NumPy для рівності (де рівність визначається як: A = B iff для всіх індексів i:) A[i] == B[i]?

Просто використання ==дає мені булевий масив:

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

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

Чи потрібно мені andелементами цього масиву визначати, чи рівні масиви рівні, чи існує більш простий спосіб порівняння?

Відповіді:


380
(A==B).all()

перевірити, чи всі значення масиву (A == B) є True.

Примітка. Можливо, ви також хочете перевірити форму A і B, наприклад A.shape == B.shape

Особливі випадки та альтернативи (з відповіді dbaupp та коментаря yoavram)

Слід зазначити, що:

  • це рішення може мати дивну поведінку в конкретному випадку: якщо Aабо Bпорожній, а інший містить один елемент, він повертається True. Чомусь порівняння A==Bповертає порожній масив, для якого allповертається оператор True.
  • Ще один ризик, якщо Aі Bне мають ту ж форму і не broadcastable, то цей підхід викличе помилку.

У висновку, якщо у вас є сумніви щодо приводу Aі Bформа або просто хочуть бути в безпеці: використання однієї із спеціалізованих функцій:

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
Ви майже завжди хочете np.array_equalIME. (A==B).all()буде вилітати , якщо А і В мають різну довжину . За станом на 1.10, у такому випадку == викликає попередження про депресію .
Вільфред Х'юз

У вас хороший момент, але якщо у мене виникають сумніви щодо форми, я зазвичай вважаю за краще безпосередньо перевірити її перед значенням. Тоді помилка очевидно на фігурах, які мають зовсім інше значення, ніж мають різні значення. Але це, мабуть, залежить від кожного випадку використання
1818

2
Інший ризик - якщо масиви містять нан. У такому випадку ви отримаєте помилковість, тому що nan! = Nan
Vincenzooo

1
Добре це вказати. Однак я вважаю, що це логічно, оскільки це nan!=nanозначає array(nan)!=array(nan).
Juh_

Я не розумію такої поведінки: 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 - це унітарна матриця, тому H x H.T.conj- матриця тотожності. Але np.array_equalповертається Неправдиво
Декс

91

(A==B).all()Рішення дуже акуратно, але є деякі вбудовані функції для виконання цього завдання. А саме array_equal, allcloseі array_equiv.

(Хоча деякі швидкі тестування з, timeitздається, вказують на те, що (A==B).all()метод є найшвидшим, що є дещо своєрідним, враховуючи, що він повинен виділити цілий новий масив.)


15
ви праві, за винятком того, що якщо один із порівняних масивів порожній, ви отримаєте неправильну відповідь (A==B).all(). Наприклад, спробуйте:, (np.array([1])==np.array([])).all()він дає True, а np.array_equal(np.array([1]), np.array([]))даєFalse
yoavram

1
Я також виявив і цю різницю в ефективності. Це дивно, тому що якщо у вас є два масиви, які абсолютно різні, (a==b).all()це все-таки швидше, ніж np.array_equal(a, b)(який міг би просто перевірити один елемент і вийшов).
Айдан Кейн

np.array_equalтакож працює з lists of arraysі dicts of arrays. Це може бути причиною зниження продуктивності.
Бернхард

Велике спасибі за функцію allclose, саме це мені було потрібно для чисельних обчислень. Він порівнює рівність векторів у межах допуску . :)
loved.by.Jesus

Зауважте, що np.array_equiv([1,1,1], 1) is True. Це пояснюється тим, що: " Послідовна форма" означає, що вони або однакової форми, або один вхідний масив може транслюватися, щоб створити таку ж форму, як і інший.
EliadL

13

Давайте вимірюємо продуктивність, використовуючи наступний фрагмент коду.

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)

Вихідні дані

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

Відповідно до наведених вище результатів, методи numpy здаються швидшими, ніж комбінація оператора == та методу all (), а порівняння методів numpy найшвидшим - це метод numpy.array_equal .


4
Ви повинні використовувати більший розмір масиву, який потребує принаймні секунди, щоб збільшити точність експерименту.
Вік'ят Агарвал

Це також відтворюється при зміні порядку порівняння? або повторно вводити A і B у випадкові випадки? Цю різницю можна пояснити також кешуванням пам’яті A і B комірок.
Або Громан

3
Немає суттєвої різниці між цими термінами.
До 마 SE

13

Якщо ви хочете перевірити, чи мають два масиви однакові shapeІ elementsвам слід скористатися, np.array_equalоскільки це метод, рекомендований у документації.

Не очікуйте, що будь-яка перевірка рівності переможе іншу, оскільки для оптимізації не так багато місця comparing two elements. Тільки заради, я все-таки робив кілька тестів.

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

Так майже рівно, про швидкість говорити не потрібно.

В (A==B).all()поводиться досить багато , як в наступному фрагменті коду:

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

5

Зазвичай два масиви матимуть невеликі числові помилки,

Ви можете використовувати numpy.allclose(A,B)замість цього (A==B).all(). Це повертає бул True / False


0

Тепер використовуйте np.array_equal. З документації:

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
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.