J'ai besoin de calculer le nombre d'éléments non-NaN dans une matrice ndarray numpy. Comment faire cela efficacement en Python? Voici mon code simple pour y parvenir:
import numpy as np
def numberOfNonNans(data):
count = 0
for i in data:
if not np.isnan(i):
count += 1
return count
Existe-t-il une fonction intégrée pour cela dans numpy? L'efficacité est importante car je fais des analyses Big Data.
Thnx pour toute aide!
sum(not np.isnan(x) for x in a)
, mais en termes de vitesse, elle est lente par rapport à la version numpy @ M4rtini.Réponses:
~
inverse la matrice booléenne renvoyée parnp.isnan
.np.count_nonzero
compte les valeurs qui ne sont pas 0 \ false..sum
devrait donner le même résultat. Mais peut-être plus clairement à utilisercount_nonzero
Vitesse de test:
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))
semble à peine être le plus rapide ici. d'autres données peuvent donner des résultats de vitesse relative différents.la source
numpy.isnan(array).sum()
? Je ne suis pas très compétent avec numpy cependant.data.size - np.isnan(data).sum()
sera légèrement plus efficace.Alternative rapide à écrire
Même si ce n'est pas le choix le plus rapide, si les performances ne sont pas un problème, vous pouvez utiliser:
sum(~np.isnan(data))
.Performance:
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
la source
len
place.Pour déterminer si le tableau est clairsemé, il peut être utile d'obtenir une proportion de valeurs nan
Si cette proportion dépasse un seuil, utilisez un tableau fragmenté, par exemple - https://sparse.pydata.org/en/latest/
la source
Une alternative, mais un peu plus lente, consiste à le faire sur l'indexation.
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
La double utilisation de
np.isnan(data)
et de l'==
opérateur peut être un peu exagérée et j'ai donc posté la réponse uniquement par souci d'exhaustivité.la source