Мне нужно вычислить количество элементов, отличных от NaN, в матрице numpy ndarray. Как можно эффективно сделать это в Python? Вот мой простой код для этого:
import numpy as np
def numberOfNonNans(data):
count = 0
for i in data:
if not np.isnan(i):
count += 1
return count
Есть ли для этого встроенная функция в numpy? Эффективность важна, потому что я занимаюсь анализом больших данных.
Спасибо за любую помощь!
sum(not np.isnan(x) for x in a)
, но с точки зрения скорости она медленная по сравнению с версией @ M4rtini numpy.Ответы:
~
инвертирует булеву матрицу, возвращенную изnp.isnan
.np.count_nonzero
считает значения, отличные от 0 \ false..sum
должен дать такой же результат. Но, может быть, более понятно использоватьcount_nonzero
Скорость тестирования:
In [23]: data = np.random.random((10000,10000)) In [24]: data[[np.random.random_integers(0,10000, 100)],:][:, [np.random.random_integers(0,99, 100)]] = np.nan In [25]: %timeit data.size - np.count_nonzero(np.isnan(data)) 1 loops, best of 3: 309 ms per loop In [26]: %timeit np.count_nonzero(~np.isnan(data)) 1 loops, best of 3: 345 ms per loop In [27]: %timeit data.size - np.isnan(data).sum() 1 loops, best of 3: 339 ms per loop
data.size - np.count_nonzero(np.isnan(data))
здесь едва ли может быть самым быстрым. другие данные могут дать другие результаты относительной скорости.источник
numpy.isnan(array).sum()
? Хотя я не очень разбираюсь в numpy.data.size - np.isnan(data).sum()
будет немного эффективнее.Быстро пишущая альтернатива
Хотя это не самый быстрый выбор, если производительность не является проблемой, вы можете использовать:
sum(~np.isnan(data))
.Производительность:
In [7]: %timeit data.size - np.count_nonzero(np.isnan(data)) 10 loops, best of 3: 67.5 ms per loop In [8]: %timeit sum(~np.isnan(data)) 10 loops, best of 3: 154 ms per loop In [9]: %timeit np.sum(~np.isnan(data)) 10 loops, best of 3: 140 ms per loop
источник
len
Вместо этого вы должны использовать .Чтобы определить, является ли массив разреженным, может помочь получить пропорцию значений nan
Если эта доля превышает пороговое значение, используйте разреженный массив, например - https://sparse.pydata.org/en/latest/
источник
Альтернатива, но немного более медленная - это сделать это вместо индексации.
np.isnan(data)[np.isnan(data) == False].size In [30]: %timeit np.isnan(data)[np.isnan(data) == False].size 1 loops, best of 3: 498 ms per loop
Двойное использование
np.isnan(data)
и==
оператора может быть немного излишним, поэтому я опубликовал ответ только для полноты.источник