Menghitung jumlah elemen non-NaN dalam ndarray numpy dengan Python


90

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!


2
Pertanyaan ini tampaknya di luar topik karena termasuk dalam codereview.stackexchange.com
jonrsharpe

1
Maksud Anda efisien dalam hal memori?
Ashwini Chaudhary

+1 Saya sedang berpikir tentang waktu CPU, tapi ya mengapa tidak memori juga. Lebih cepat dan lebih murah lebih baik =)
jjepsuomi

3
@jjepsuomi Sebuah versi yang hemat memori sum(not np.isnan(x) for x in a), tetapi dalam hal kecepatannya lambat dibandingkan dengan versi numpy @ M4rtini.
Ashwini Chaudhary

@AshwiniChaudhary Terima kasih banyak! Saya perlu melihat mana yang lebih penting dalam lamaran saya =)
jjepsuomi

Jawaban:


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

~membalikkan matriks boolean yang dikembalikan np.isnan.

np.count_nonzeromenghitung nilai yang bukan 0 \ false. .sumharus 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.


+1 @ M4rtini terima kasih lagi! Kamu hebat! ; DI akan menerima jawaban Anda secepat saya bisa :)
jjepsuomi

3
Bahkan mungkin numpy.isnan(array).sum()? Saya tidak terlalu mahir dengan numpy.
msvalkon

2
@msvalkon, Ini akan menghitung jumlah NaN, sedangkan OP menginginkan jumlah elemen non-NaN.
falsetru


5
Perpanjangan jawaban @msvalkon: data.size - np.isnan(data).sum()akan sedikit lebih efisien.
Daniel

11

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

Jawaban ini memberikan jumlah yang tidak sama dengan menghitung jumlah elemen ... Anda harus menggunakan lensebagai gantinya.
BenT

1
@BenT Jumlah elemen array bool yang memenuhi kondisi tertentu sama dengan memberikan len dari subset array dengan elemen yang memenuhi kondisi tertentu. Bisakah Anda menjelaskan di mana kesalahan ini?
GM

2
Kesalahan saya, saya lupa Boolean dikembalikan.
BenT

3

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.


Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.