Preciso calcular o número de elementos não NaN em uma matriz ndarray numpy. Como alguém faria isso com eficiência em Python? Aqui está meu código simples para conseguir isso:
import numpy as np
def numberOfNonNans(data):
count = 0
for i in data:
if not np.isnan(i):
count += 1
return count
Existe uma função interna para isso no numpy? A eficiência é importante porque estou fazendo análises de Big Data.
Thnx por qualquer ajuda!
sum(not np.isnan(x) for x in a)
, mas em termos de velocidade é lenta comparada à versão numpy do @M4rtini.Respostas:
~
inverte a matriz booleana de onde retornounp.isnan
.np.count_nonzero
conta valores que não são 0 \ false..sum
deve dar o mesmo resultado. Mas talvez de forma mais clara para usarcount_nonzero
Velocidade de teste:
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))
parece quase não ser o mais rápido aqui. outros dados podem fornecer resultados de velocidade relativa diferentes.fonte
numpy.isnan(array).sum()
? Não sou muito proficiente com entorpecimento.data.size - np.isnan(data).sum()
será um pouco mais eficiente.Alternativa rápida de escrever
Embora não seja a escolha mais rápida, se o desempenho não for um problema, você pode usar:
sum(~np.isnan(data))
.Atuação:
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
fonte
len
lugar.Para determinar se a matriz é esparsa, pode ajudar obter uma proporção dos valores nan
Se essa proporção exceder um limite, use uma matriz esparsa, por exemplo - https://sparse.pydata.org/en/latest/
fonte
Uma alternativa, mas um pouco mais lenta, é fazer isso sobre a indexação.
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
O uso duplo de
np.isnan(data)
e do==
operador pode ser um pouco exagerado, então publiquei a resposta apenas para completar.fonte