Saya perlu menghitung jumlah elemen non-NaN dalam matriks ndarray numpy. Bagaimana cara melakukan ini secara efisien dengan Python? Inilah kode sederhana saya untuk mencapai ini:
import numpy as np
def numberOfNonNans(data):
count = 0
for i in data:
if not np.isnan(i):
count += 1
return count
Apakah ada fungsi bawaan untuk ini di numpy? Efisiensi itu penting karena saya melakukan analisis Big Data.
Terima kasih atas bantuannya!
sum(not np.isnan(x) for x in a)
, tetapi dalam hal kecepatannya lambat dibandingkan dengan versi numpy @ M4rtini.Jawaban:
~
membalikkan matriks boolean yang dikembalikannp.isnan
.np.count_nonzero
menghitung nilai yang bukan 0 \ false..sum
harus memberikan hasil yang sama. Tapi mungkin lebih jelas untuk digunakancount_nonzero
Kecepatan pengujian:
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))
sepertinya hampir tidak menjadi yang tercepat di sini. data lain mungkin memberikan hasil kecepatan relatif yang berbeda.sumber
numpy.isnan(array).sum()
? Saya tidak terlalu mahir dengan numpy.data.size - np.isnan(data).sum()
akan sedikit lebih efisien.Alternatif cepat untuk menulis
Meskipun bukan pilihan tercepat, jika kinerja bukan masalah, Anda dapat menggunakan:
sum(~np.isnan(data))
.Performa:
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
sumber
len
sebagai gantinya.Alternatif, tetapi alternatif yang sedikit lebih lambat adalah melakukannya melalui pengindeksan.
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
Penggunaan ganda
np.isnan(data)
dan==
operator mungkin sedikit berlebihan dan jadi saya memposting jawaban hanya untuk kelengkapan.sumber
Untuk menentukan apakah lariknya jarang, mungkin membantu untuk mendapatkan proporsi nilai nan
np.isnan(ndarr).sum() / ndarr.size
Jika proporsi itu melebihi ambang batas, gunakan larik renggang, misalnya - https://sparse.pydata.org/en/latest/
sumber