Muszę obliczyć liczbę elementów innych niż NaN w macierzy numpy ndarray. Jak można to skutecznie zrobić w Pythonie? Oto mój prosty kod do osiągnięcia tego:
import numpy as np
def numberOfNonNans(data):
count = 0
for i in data:
if not np.isnan(i):
count += 1
return count
Czy jest do tego wbudowana funkcja w Numpy? Wydajność jest ważna, ponieważ zajmuję się analizą Big Data.
Dziękuję za pomoc!
sum(not np.isnan(x) for x in a)
pod względem pamięci , ale pod względem szybkości jest wolna w porównaniu z wersją @ M4rtini numpy.Odpowiedzi:
~
odwraca macierz boolowską zwróconą znp.isnan
.np.count_nonzero
zlicza wartości inne niż 0 \ false..sum
powinien dać ten sam wynik. Ale może jaśniej w użyciucount_nonzero
Prędkość testowania:
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))
wydaje się być tutaj ledwo najszybszy. inne dane mogą dawać inne względne wyniki prędkości.źródło
numpy.isnan(array).sum()
? Nie jestem jednak biegły w odrętwieniu.data.size - np.isnan(data).sum()
będzie nieco wydajniejsze.Alternatywa do szybkiego zapisu
Chociaż nie jest to najszybszy wybór, jeśli wydajność nie jest problemem, możesz użyć:
sum(~np.isnan(data))
.Występ:
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
źródło
len
.Aby określić, czy tablica jest rzadka, pomocne może być uzyskanie proporcji wartości nan
Jeśli ta proporcja przekracza próg, użyj rzadkiej tablicy, np. - https://sparse.pydata.org/en/latest/
źródło
Alternatywą, ale nieco wolniejszą, jest wykonanie tego przez indeksowanie.
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
Podwójne zastosowanie
np.isnan(data)
, a==
operator może być trochę przesada i tak napisałem odpowiedź tylko dla kompletności.źródło