mengubah nilai nan menjadi nol

95

Saya memiliki array numpy 2D. Beberapa nilai dalam array ini adalah NaN. Saya ingin melakukan operasi tertentu menggunakan larik ini. Misalnya perhatikan array:

[[   0.   43.   67.    0.   38.]
 [ 100.   86.   96.  100.   94.]
 [  76.   79.   83.   89.   56.]
 [  88.   NaN   67.   89.   81.]
 [  94.   79.   67.   89.   69.]
 [  88.   79.   58.   72.   63.]
 [  76.   79.   71.   67.   56.]
 [  71.   71.   NaN   56.  100.]]

Saya mencoba untuk mengambil setiap baris, satu per satu, mengurutkannya dalam urutan terbalik untuk mendapatkan nilai maksimal 3 dari baris dan mengambil rata-ratanya. Kode yang saya coba adalah:

# nparr is a 2D numpy array
for entry in nparr:
    sortedentry = sorted(entry, reverse=True)
    highest_3_values = sortedentry[:3]
    avg_highest_3 = float(sum(highest_3_values)) / 3

Ini tidak berfungsi untuk baris yang berisi NaN. Pertanyaan saya adalah, apakah ada cara cepat untuk mengubah semua NaNnilai menjadi nol dalam larik numpy 2D sehingga saya tidak memiliki masalah dengan pengurutan dan hal lain yang saya coba lakukan.

Curious2learn
sumber
1
each: map: return isNaN(value) ? 0 : value
Kiroid
@kirilloid: kedengarannya bagus, bagaimana dengan contoh penggunaan?
serv-inc

Jawaban:

124

Ini harus bekerja:

from numpy import *

a = array([[1, 2, 3], [0, 3, NaN]])
where_are_NaNs = isnan(a)
a[where_are_NaNs] = 0

Dalam kasus di atas di mana_are_NaNs adalah:

In [12]: where_are_NaNs
Out[12]: 
array([[False, False, False],
       [False, False,  True]], dtype=bool)
Marcin
sumber
139

Di mana Aarray 2D Anda:

import numpy as np
A[np.isnan(A)] = 0

Fungsi tersebut isnanmenghasilkan array bool yang menunjukkan di mana NaNnilai-nilainya berada. Array boolean dapat digunakan untuk mengindeks larik dengan bentuk yang sama. Anggap saja seperti topeng.

Paul
sumber
40

Bagaimana dengan nan_to_num () ?

Drake Guan
sumber
11
nan_to_num () juga mengubah tak terbatas - ini mungkin tidak diinginkan dalam beberapa kasus.
Agos
11
Ini juga> 10x lebih lambat dari metode lainnya.
pengguna48956
7
Saya tidak yakin tentang pernyataan tat "> 10x lambat" jadi saya memeriksanya. Memang, itu jauh lebih lambat. Terima kasih telah menunjukkan hal ini.
Gabriel
16

Anda dapat menggunakan np.whereuntuk menemukan di mana Anda memiliki NaN:

import numpy as np

a = np.array([[   0,   43,   67,    0,   38],
              [ 100,   86,   96,  100,   94],
              [  76,   79,   83,   89,   56],
              [  88,   np.nan,   67,   89,   81],
              [  94,   79,   67,   89,   69],
              [  88,   79,   58,   72,   63],
              [  76,   79,   71,   67,   56],
              [  71,   71,   np.nan,   56,  100]])

b = np.where(np.isnan(a), 0, a)

In [20]: b
Out[20]: 
array([[   0.,   43.,   67.,    0.,   38.],
       [ 100.,   86.,   96.,  100.,   94.],
       [  76.,   79.,   83.,   89.,   56.],
       [  88.,    0.,   67.,   89.,   81.],
       [  94.,   79.,   67.,   89.,   69.],
       [  88.,   79.,   58.,   72.,   63.],
       [  76.,   79.,   71.,   67.,   56.],
       [  71.,   71.,    0.,   56.,  100.]])
Anton Protopopov
sumber
1
karena apa adanya, ini tidak berfungsi, Anda perlu mengubahnya np.where(np.isnan(a), a, 0)ke np.where(~np.isnan(a), a, 0). Ini mungkin perbedaan dalam versi yang digunakan.
TehTris
1
@TehTris Anda benar, terima kasih. Saya mengubahnya menjadi b = np.where(np.isnan(a), 0, a)yang lebih mudah daripada yang ~saya pikirkan.
Anton Protopopov
11

Contoh kode jawaban drake untuk digunakan nan_to_num:

>>> import numpy as np
>>> A = np.array([[1, 2, 3], [0, 3, np.NaN]])
>>> A = np.nan_to_num(A)
>>> A
array([[ 1.,  2.,  3.],
       [ 0.,  3.,  0.]])
serv-inc
sumber
3

Anda dapat menggunakan numpy.nan_to_num :

numpy.nan_to_num (x): Gantikan nan dengan nol dan inf dengan angka terbatas .

Contoh (lihat dokumen):

>>> np.set_printoptions(precision=8)
>>> x = np.array([np.inf, -np.inf, np.nan, -128, 128])
>>> np.nan_to_num(x)
array([  1.79769313e+308,  -1.79769313e+308,   0.00000000e+000,
        -1.28000000e+002,   1.28000000e+002])
Bilal
sumber
1

nan tidak pernah sama dengan nan

if z!=z:z=0

jadi untuk array 2D

for entry in nparr:
    if entry!=entry:entry=0
litepresence
sumber
Ini tidak bekerja: entryadalah larik 1D, jadi pengujian entry != entrytidak memberikan boolean sederhana tetapi memunculkan ValueError.
Eric O Lebigot
-1

Anda dapat menggunakan fungsi lambda, contoh untuk array 1D:

import numpy as np
a = [np.nan, 2, 3]
map(lambda v:0 if np.isnan(v) == True else v, a)

Ini akan memberi Anda hasil:

[0, 2, 3]
Mohanad Kaleia
sumber
-8

Untuk tujuan Anda, jika semua item disimpan sebagai strdan Anda hanya menggunakan disortir seperti yang Anda gunakan lalu periksa elemen pertama dan ganti dengan '0'

>>> l1 = ['88','NaN','67','89','81']
>>> n = sorted(l1,reverse=True)
['NaN', '89', '88', '81', '67']
>>> import math
>>> if math.isnan(float(n[0])):
...     n[0] = '0'
... 
>>> n
['0', '89', '88', '81', '67']
Senthil Kumaran
sumber
6
Bukankah komentar Anda agak kasar? Saya tahu apa itu numpy, tetapi saya tahu bahwa array tidak akan menjadi representasi string dari angka. Saya secara khusus tidak memberikan pandangan ini dari perspektif numpy tetapi dari perspektif python, jika itu berguna.
Senthil Kumaran
2
Mengurutkan ulang array sepertinya merupakan cara yang membingungkan untuk menyelesaikan masalah ini.
holografix
Saya perlu mempertahankan urutan array saya. Ini tidak akan berfungsi jika Anda memiliki beberapa 'NaN' dalam array Anda.
3nrique0