Сравнение двух массивов NumPy на равенство поэлементно

254

Какой самый простой способ сравнить два массива NumPy на равенство (где равенство определяется как: A = B тогда и только для всех индексов i:) A[i] == B[i]?

Простое использование ==дает мне логический массив:

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

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

Обязательно ли andэлементы этого массива, чтобы определить, равны ли массивы, или есть более простой способ сравнения?

clstaudt
источник

Ответы:

382
(A==B).all()

проверить, все ли значения массива (A == B) равны True.

Примечание: возможно, вы также хотите проверить форму A и B, например: A.shape == B.shape

Особые случаи и альтернативы (из ответа dbaupp и комментария yoavram)

Следует отметить, что:

  • это решение может иметь странное поведение в конкретном случае: если одно Aили Bпусто, а другое содержит один элемент, оно возвращается True. По какой-то причине сравнение A==Bвозвращает пустой массив, для которого allвозвращается оператор True.
  • Другой риск состоит в том, что если Aи Bне имеют одинаковую форму и не могут быть переданы, то такой подход вызовет ошибку.

В заключение, если у вас есть сомнения по поводу 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
Juh_
источник
27
Вы почти всегда хотите np.array_equalIME. (A==B).all()произойдет сбой, если A и B имеют разную длину . Начиная с версии 1.10, == в этом случае выдает предупреждение об устаревании .
Уилфред Хьюз
У вас есть хорошая точка зрения, но в случае, если у меня есть сомнения по поводу формы, я обычно предпочитаю проверить ее непосредственно перед значением. Тогда ошибка явно связана с формами, которые имеют совершенно другое значение, чем имеющие разные значения. Но это , вероятно , зависит от каждого сценария использования
Juh_
2
Еще один риск, если массивы содержат Nan. В этом случае вы получите False, потому что 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возвращает Ложь
Декс
92

(A==B).all()Решение очень аккуратно, но есть некоторые встроенные функции для выполнения этой задачи. А именно array_equal, allcloseа array_equiv.

(Хотя некоторые быстрые тесты, по- timeitвидимому, указывают на то, что (A==B).all()метод является самым быстрым, что немного странно, учитывая, что ему нужно выделить целый новый массив.)

Юон
источник
16
Вы правы, за исключением того, что если один из сравниваемых массивов пуст, вы получите неправильный ответ (A==B).all(). Например, попробуйте:, (np.array([1])==np.array([])).all()он дает True, а np.array_equal(np.array([1]), np.array([]))даетFalse
йоаврам
1
Я только что обнаружил эту разницу в производительности тоже. Это странно, потому что если у вас есть 2 совершенно разных массива, это (a==b).all()все равно быстрее, чем np.array_equal(a, b)(который мог бы просто проверить один элемент и выйти).
Эйдан Кейн,
np.array_equalтакже работает с lists of arraysи dicts of arrays. Это может быть причиной снижения производительности.
Бернхард
Большое спасибо за функцию allclose, это то, что мне нужно для численных расчетов. Он сравнивает равенство векторов в пределах допуска . :)
love.by.Иесус
Обратите внимание, что np.array_equiv([1,1,1], 1) is True. Это связано с тем, что: согласованная форма означает, что они либо имеют одинаковую форму, либо один входной массив может быть передан для создания такой же формы, что и другой.
ЭлиадЛ
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 .

испуг
источник
5
Вы должны использовать больший размер массива, для компиляции которого требуется не менее секунды, чтобы повысить точность эксперимента.
Вихьят Агарвал
Это также воспроизводится при изменении порядка сравнения? или каждый раз переставлять A и B в случайный порядок? Эта разница также может быть объяснена кэшированием в памяти ячеек А и В.
Или Громан
4
Там нет значимой разницы между этими временами.
마 SE SE
13

Если вы хотите проверить, имеют ли два массива одинаковые shapeAND 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
user1767754
источник
5

Обычно два массива будут иметь небольшие числовые ошибки,

Вы можете использовать numpy.allclose(A,B)вместо (A==B).all(). Возвращает bool 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
keramat
источник