Python'da bir ndarray'deki NaN olmayan öğelerin sayısını sayma


90

Bir ndarray matrisindeki NaN olmayan elemanların sayısını hesaplamam gerekiyor. Python'da bunu nasıl verimli bir şekilde yapabilirsiniz? İşte bunu başarmak için benim basit kodum:

import numpy as np

def numberOfNonNans(data):
    count = 0
    for i in data:
        if not np.isnan(i):
            count += 1
    return count 

Bunun için numpy'de yerleşik bir işlev var mı? Verimlilik önemli çünkü Büyük Veri analizi yapıyorum.

Herhangi bir yardım için teşekkürler!



1
Hafıza açısından verimli mi demek istiyorsun?
Ashwini Chaudhary

+1 CPU zamanı hakkında düşünüyordum, ama evet neden bellek de değil. Ne kadar hızlı ve ucuz o kadar iyi =)
jjepsuomi

3
@jjepsuomi Hafızayı verimli kullanan bir sürüm olacaktır sum(not np.isnan(x) for x in a), ancak hız açısından @ M4rtini uyuşmuş sürümüne kıyasla yavaştır.
Ashwini Chaudhary

@AshwiniChaudhary Çok teşekkür ederim! Başvurumda hangisinin daha önemli olduğunu görmem gerekiyor =)
jjepsuomi

Yanıtlar:


164
np.count_nonzero(~np.isnan(data))

~döndürülen boole matrisini tersine çevirir np.isnan.

np.count_nonzero0 \ false olmayan değerleri sayar. .sumaynı sonucu vermelidir. Ama belki daha net kullanmakcount_nonzero

Test hızı:

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))Burada zar zor en hızlısı gibi görünüyor. diğer veriler farklı göreceli hız sonuçları verebilir.


+1 @ M4rtini tekrar teşekkür ederim! Sen müthişsin! ; DI,
elimden geldiğince

3
Hatta belki numpy.isnan(array).sum()? Yine de uyuşukluk konusunda pek usta değilim.
msvalkon

2
@msvalkon, NaN sayısını sayarken OP, NaN olmayan elemanların sayısını ister.
falsetru


5
@Msvalkon yanıtının bir uzantısı: data.size - np.isnan(data).sum()biraz daha verimli olacaktır.
Daniel

11

Hızlı yazma alternatifli

En hızlı seçim olmasa da, performans bir sorun değilse şunları kullanabilirsiniz:

sum(~np.isnan(data)).

Verim:

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

Bu cevap element sayısını saymakla aynı olmayan toplamı sağlar ... Onun lenyerine kullanmalısınız .
BenT

1
@BenT Belirli bir koşulu karşılayan bir bool dizisi öğelerinin toplamı, bir alt küme dizisinin uzunluğunu belirli bir koşulu karşılayan öğelerle sağladığında aynıdır. Bunun nerede yanlış olduğunu açıklar mısınız lütfen?
GM

2
Benim hatam bir Boolean'ın dönüşünü unuttum.
BenT

3

Bir alternatif, ancak biraz daha yavaş bir alternatif, bunu indekslemeye göre yapmaktır.

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 

Çifte kullanımı np.isnan(data)ve ==operatör biraz overkill ve sadece tamlığı için cevap yayınlanmıştır yüzden olabilir.


3

Dizinin seyrek olup olmadığını belirlemek için nan değerlerinin bir oranını elde etmek yardımcı olabilir.

np.isnan(ndarr).sum() / ndarr.size

Bu oran bir eşiği aşarsa, seyrek bir dizi kullanın, örneğin - https://sparse.pydata.org/en/latest/

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.