сравнивая массивы numy, содержащие NaN

Для моего юнит-теста я хочу проверить, идентичны ли два массива. Сокращенный пример:

a = np.array([1, 2, np.NaN])
b = np.array([1, 2, np.NaN])
if np.all(a==b):
    print 'arrays are equal'

Это не работает, потому что nan! = Nan. Каков наилучший способ продолжить?

Заранее спасибо.

Ответы на вопрос(6)

Я не уверен, что этоbest способ продолжить, но этоa путь:

>>> ((a == b) | (numpy.isnan(a) & numpy.isnan(b))).all()
True
 02 мар. 2014 г., 15:25
Мне очень нравится простота этого. Кроме того, оно кажется более быстрым, чем решение @Avaris. Превращая это в лямбда-функцию, тестирование с Ipython%timeit дает 23,7 мкс против 1,01 мс.
 02 мар. 2014 г., 17:46
Нет, я только что провел простой тест, с некоторыми вещаниями, относящимися к моей проблеме (сравнил 2D массив с 1D вектором & # x2013; так что я думаю, что это было сравнение по строкам). Но я думаю, что можно довольно легко провести много тестов в ноутбуке Ipython. Кроме того, я использовал лямбда-функцию для вашего решения, но я думаю, что она должна быть немного быстрее, если бы я использовал обычную функцию (часто кажется, что так).
 22 мая 2012 г., 23:34
+1 Это решение кажется немного более быстрым, чем решение, которое я выложил с использованием масочных массивов, хотя, если бы вы создавали маску для использования в других частях вашего кода, издержки на создание маски стали бы меньшим фактором в общем эффективность сделанной стратегии.
 saroele24 мая 2012 г., 00:43
Благодарю. Ваше решение действительно работает, но я предпочитаю встроенный тест в Numpy, как предложено Avaris
 02 мар. 2014 г., 16:10
@NovicePhysicist, интересное время! Интересно, связано ли это с использованием обработки исключений. Были ли у вас положительные или отрицательные результаты? Скорость, вероятно, будет значительно различаться в зависимости от того, было ли выброшено исключение или нет.
Решение Вопроса

В качестве альтернативы вы можете использоватьnumpy.testing.assert_equal или жеnumpy.testing.assert_array_equal сtry/except:

In : import numpy as np

In : def nan_equal(a,b):
...:     try:
...:         np.testing.assert_equal(a,b)
...:     except AssertionError:
...:         return False
...:     return True

In : a=np.array([1, 2, np.NaN])

In : b=np.array([1, 2, np.NaN])

In : nan_equal(a,b)
Out: True

In : a=np.array([1, 2, np.NaN])

In : b=np.array([3, 2, np.NaN])

In : nan_equal(a,b)
Out: False

Edit

Поскольку вы используете это для юнит-тестирования, голыеassert (вместо того, чтобы обернуть его, чтобы получитьTrue/False) может быть более естественным.

 14 июн. 2013 г., 12:14
Обратите внимание, что это решение работает, потому чтоnumpy.testing.assert_* не придерживаться той же семантики Pythonassert& APOS; с. В простом PythonAssertionError исключения подняты, если__debug__ is True то есть, если сценарий выполняется без оптимизации (без флага -O), см.docs, По этой причине я бы настоятельно не рекомендовал упаковкуAssertionErrors для контроля потока. Конечно, поскольку мы находимся в тестовом наборе, лучшим решением будет оставить numpy.testing.assert в покое.
 saroele24 мая 2012 г., 00:42
Отлично, это самое элегантное и встроенное решение. Я только добавилnp.testing.assert_equal(a,b) в моем unittest, и если это вызывает исключение, тест не пройден (без ошибок), и я даже получаю хороший отпечаток с различиями и несоответствием. Благодарю.
 08 авг. 2018 г., 15:57
Документацияnumpy.testing.assert_equal() явно не означает, что он считает, что NaN равен NaN (тогда какnumpy.testing.assert_array_equal() делает): это это задокументировано где-то еще?

Самый простой способ - это использованиеnumpy.allclose() метод, позволяющий определить поведение при наличии значений нан. Тогда ваш пример будет выглядеть следующим образом:

a = np.array([1, 2, np.nan])
b = np.array([1, 2, np.nan])

if np.allclose(a, b, equal_nan=True):
    print 'arrays are equal'

затемarrays are equal будет напечатан.

Ты можешь найтиВот сопутствующая документация

 06 мар. 2018 г., 15:51
+1, потому что ваше решение не изобретает велосипед. Однако это работает только с элементами, подобными числам. В противном случае вы получите противныйTypeError: ufunc 'isfinite' not supported for the input types, and the inputs could not be safely coerced to any supported types according to the casting rule ''safe''
 11 дек. 2018 г., 00:41
Это отличный ответ во многих контекстах! Стоит добавить предупреждение о том, что это вернет истину, даже если массивы не являются строго равными. Хотя в большинстве случаев это не имеет значения.

Когда я использовал приведенный выше ответ:

 ((a == b) | (numpy.isnan(a) & numpy.isnan(b))).all()

Это дало мне несколько ошибок при оценке списка строк.

Это более общий тип:

def EQUAL(a,b):
    return ((a == b) | ((a != a) & (b != b)))

Если вы делаете это для таких вещей, какunit tests, так что вы не очень заботитесь о производительности и "правильности" поведение со всеми типами, вы можете использовать этоto have something that works with all types of arrays, not just numeric:

a = np.array(['a', 'b', None])
b = np.array(['a', 'b', None])
assert list(a) == list(b)

Casting ndarrays to lists Иногда может быть полезно получить желаемое поведение в каком-то тесте. (Но не используйте это в производственном коде или с большими массивами!)

Вы могли бы использовать массивные массивы, маскироватьNaN значения, а затем использоватьnumpy.ma.all или жеnumpy.ma.allclose:

http://docs.scipy.org/doc/numpy/reference/generated/numpy.ma.all.html

http://docs.scipy.org/doc/numpy/reference/generated/numpy.ma.allclose.html

Например:

a=np.array([1, 2, np.NaN])
b=np.array([1, 2, np.NaN])
np.ma.all(np.ma.masked_invalid(a) == np.ma.masked_invalid(b)) #True
 saroele24 мая 2012 г., 00:43
спасибо, что сообщили мне об использовании замаскированных массивов. Однако я предпочитаю решение Avaris.
 24 сент. 2014 г., 04:33
Вы должны использоватьnp.ma.masked_where(np.isnan(a), a) иначе вы не сможете сравнить бесконечные значения.
 05 янв. 2017 г., 15:41
Я проверил сa=np.array([1, 2, np.NaN]) а такжеb=np.array([1, np.NaN, 2])  которые явно не равны иnp.ma.all(np.ma.masked_invalid(a) == np.ma.masked_invalid(b)) все еще возвращает True, так что имейте это в виду, если вы используете этот метод.

Ваш ответ на вопрос