Определить, содержит ли массив NumPy хотя бы одно нечисловое значение? - PullRequest
77 голосов
/ 26 мая 2009

Мне нужно написать функцию, которая будет определять, содержит ли вход хотя бы одно не числовое значение. Если не числовое значение будет найдено, я выдам ошибку (потому что вычисление должно возвращать только числовое значение). Количество измерений входного массива заранее неизвестно - функция должна давать правильное значение независимо от ndim. В качестве дополнительного усложнения входными данными может быть одиночное число с плавающей запятой или numpy.float64, или даже что-то странное, похожее на нульмерный массив.

Очевидный способ решить эту проблему - написать рекурсивную функцию, которая выполняет итерацию по каждому итерируемому объекту в массиве, пока не найдет неитераб. Он будет применять функцию numpy.isnan() к каждому не повторяемому объекту. Если найдено хотя бы одно нечисловое значение, функция немедленно вернет значение False. В противном случае, если все значения в итерируемом являются числовыми, он в конечном итоге вернет True.

Это работает просто отлично, но довольно медленно, и я ожидаю, что NumPy имеет гораздо лучший способ сделать это. Какая альтернатива быстрее и тупее?

Вот мой макет:

def contains_nan( myarray ):
    """
    @param myarray : An n-dimensional array or a single float
    @type myarray : numpy.ndarray, numpy.array, float
    @returns: bool
    Returns true if myarray is numeric or only contains numeric values.
    Returns false if at least one non-numeric value exists
    Not-A-Number is given by the numpy.isnan() function.
    """
    return True

Ответы [ 4 ]

135 голосов
/ 27 мая 2009

Это должно быть быстрее, чем итерация, и будет работать независимо от формы.

numpy.isnan(myarray).any()

Редактировать: в 30 раз быстрее:

import timeit
s = 'import numpy;a = numpy.arange(10000.).reshape((100,100));a[10,10]=numpy.nan'
ms = [
    'numpy.isnan(a).any()',
    'any(numpy.isnan(x) for x in a.flatten())']
for m in ms:
    print "  %.2f s" % timeit.Timer(m, s).timeit(1000), m

Результаты:

  0.11 s numpy.isnan(a).any()
  3.75 s any(numpy.isnan(x) for x in a.flatten())

Бонус: он отлично работает для типов NumPy, не являющихся массивами:

>>> a = numpy.float64(42.)
>>> numpy.isnan(a).any()
False
>>> a = numpy.float64(numpy.nan)
>>> numpy.isnan(a).any()
True
13 голосов
/ 09 октября 2015

Если бесконечность является возможным значением, я бы использовал numpy.isfinite

numpy.isfinite(myarray).all()

Если вышеприведенное значение равно True, то myarray не содержит значений, numpy.nan, numpy.inf или -numpy.inf.

numpy.nan будет в порядке со значениями numpy.inf, например:

In [11]: import numpy as np

In [12]: b = np.array([[4, np.inf],[np.nan, -np.inf]])

In [13]: np.isnan(b)
Out[13]: 
array([[False, False],
       [ True, False]], dtype=bool)

In [14]: np.isfinite(b)
Out[14]: 
array([[ True, False],
       [False, False]], dtype=bool)
3 голосов
/ 25 августа 2009

С numpy 1.3 или SVN вы можете сделать это

In [1]: a = arange(10000.).reshape(100,100)

In [3]: isnan(a.max())
Out[3]: False

In [4]: a[50,50] = nan

In [5]: isnan(a.max())
Out[5]: True

In [6]: timeit isnan(a.max())
10000 loops, best of 3: 66.3 µs per loop

Обработка нанс в сравнении не была последовательной в более ранних версиях.

2 голосов
/ 11 мая 2017

(np.where(np.isnan(A)))[0].shape[0] будет больше 0, если A содержит хотя бы один элемент nan, A может быть n x m матрицей.

Пример:

import numpy as np

A = np.array([1,2,4,np.nan])

if (np.where(np.isnan(A)))[0].shape[0]: 
    print "A contains nan"
else:
    print "A does not contain nan"
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...