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.


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)

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.


40

Bagaimana dengan nan_to_num () ?


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.]])

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.]])

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])

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

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]

-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']

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
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.