Я ищу самый быстрый способ проверить наличие NaN ( np.nan
) в массиве NumPy X
. np.isnan(X)
не может быть и речи, поскольку он создает логический массив формы X.shape
, который потенциально может быть гигантским.
Я пробовал np.nan in X
, но, похоже, не работает, потому что np.nan != np.nan
. Есть ли вообще быстрый и эффективный с точки зрения памяти способ сделать это?
(Тем, кто спрашивает «насколько гигантский»: я не могу сказать. Это проверка ввода для кода библиотеки.)
scipy.sparse
на вход массивы или матрицы NumPy .Ответы:
Решение Рэя хорошее. Однако на моей машине это примерно в 2,5 раза быстрее
numpy.sum
вместоnumpy.min
:В отличие от этого
min
,sum
не требует разветвления, что на современном оборудовании, как правило, довольно дорого. Вероятно, поэтомуsum
он быстрее.edit Вышеупомянутый тест был выполнен с одним NaN прямо в середине массива.
Интересно отметить, что
min
в присутствии NaN происходит медленнее, чем в их отсутствие. Также кажется, что он становится медленнее по мере приближения NaN к началу массива. С другой стороны,sum
пропускная способность кажется постоянной независимо от того, есть ли NaN и где они расположены:источник
np.min
работает быстрее, когда массив не содержит NaN, что является моим ожидаемым вводом. Но я решил принять этот в любом случае, потому что она ловитinf
иneginf
как хорошо.inf
или,-inf
если входные данные содержат оба, и возникают проблемы, если входные данные содержат большие, но конечные значения, которые переполняются при сложении.np.sum
все еще примерно на 30% быстрее, чемnp.min
.np.isnan(x).any(0)
немного быстрее , чемnp.sum
иnp.min
на моей машине, хотя там могут быть некоторые нежелательные кэширование.Думаю
np.isnan(np.min(X))
надо делать то, что хочешь.источник
Даже если есть принятый ответ, я хотел бы продемонстрировать следующее (с Python 2.7.2 и Numpy 1.6.0 в Vista):
Таким образом, действительно эффективный способ может сильно зависеть от операционной системы. В любом случае, базовый
dot(.)
вариант кажется наиболее стабильным.источник
x
содержит большие значения, и я также хочу проверить inf.isfinite(.)
. Я просто хотел указать на огромный разрыв в производительности. Спасибоmin
- илиsum
-, которые работают только в одном ядре. Ergo, этот разрыв в производительности.Здесь есть два общих подхода:
nan
и возьмитеany
.nan
s (подобноеsum
), и проверьте ее результат.Хотя первый подход, безусловно, является самым чистым, тяжелая оптимизация некоторых совокупных операций (особенно тех, которые выполняются в BLAS, например
dot
) может сделать их довольно быстрыми. Обратите внимание, чтоdot
, как и некоторые другие операции BLAS, при определенных условиях выполняются многопоточные. Это объясняет разницу в скорости между разными машинами.источник
использовать .any ()
if numpy.isnan(myarray).any()
numpy.isfinite может быть лучше, чем isnan для проверки
if not np.isfinite(prop).all()
источник
Если тебе комфортно с Numba он позволяет создать функцию быстрого короткого замыкания (останавливается, как только будет найдено NaN):
Если нет,
NaN
функция может быть медленнее, чемnp.min
, я думаю, это потому, чтоnp.min
для больших массивов используется многопроцессорность:Но если в массиве есть NaN, особенно если его позиция имеет низкие индексы, тогда это намного быстрее:
Аналогичные результаты могут быть достигнуты с помощью Cython или расширения C, они немного сложнее (или легко доступны
bottleneck.anynan
), но в конечном итоге делают то же самое, что и мояanynan
функция.источник
С этим связан вопрос, как найти первое вхождение NaN. Это самый быстрый способ справиться с тем, о чем я знаю:
источник