แปลงค่านาโนเป็นศูนย์


95

ฉันมีอาร์เรย์ตัวเลข 2D NaNบางส่วนของค่าในอาร์เรย์นี้ ฉันต้องการดำเนินการบางอย่างโดยใช้อาร์เรย์นี้ ตัวอย่างเช่นพิจารณาอาร์เรย์:

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

ฉันพยายามหาแต่ละแถวทีละแถวเรียงลำดับกลับกันเพื่อให้ได้ค่าสูงสุด 3 ค่าจากแถวและหาค่าเฉลี่ย รหัสที่ฉันลองคือ:

# 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

NaNนี้ไม่ได้ทำงานสำหรับแถวที่มี คำถามของฉันคือมีวิธีที่รวดเร็วในการแปลงNaNค่าทั้งหมดเป็นศูนย์ในอาร์เรย์ 2D numpy หรือไม่เพื่อที่ฉันจะได้ไม่มีปัญหากับการเรียงลำดับและสิ่งอื่น ๆ ที่ฉันพยายามทำ


1
each: map: return isNaN(value) ? 0 : value
kirilloid

@kirilloid: ฟังดูดีตัวอย่างการใช้งานล่ะ?
บริการรวม

คำตอบ:


124

สิ่งนี้ควรใช้งานได้:

from numpy import *

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

ในกรณีข้างต้นโดยที่ _are_NaNs คือ:

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

139

Aอาร์เรย์ 2D ของคุณอยู่ที่ไหน:

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

ฟังก์ชันisnanสร้างอาร์เรย์บูลที่ระบุว่าNaNค่าอยู่ที่ไหน อาร์เรย์บูลีนสามารถใช้เพื่อสร้างดัชนีอาร์เรย์ที่มีรูปร่างเดียวกันได้ คิดว่าเหมือนหน้ากาก


40

แล้วnan_to_num ()ล่ะ?


11
nan_to_num () ยังเปลี่ยน infinities ซึ่งอาจไม่ต้องการในบางกรณี
Agos

11
มันยังช้ากว่าวิธีอื่น ๆ ถึง 10 เท่า
user48956

7
ฉันไม่แน่ใจเกี่ยวกับคำสั่ง tat "> 10x slow" ดังนั้นฉันจึงตรวจสอบ แท้จริงแล้วมันช้ากว่านั้นมาก ขอบคุณที่ชี้ให้เห็น
กาเบรียล

16

คุณสามารถใช้np.whereเพื่อค้นหาตำแหน่งที่คุณมี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
มันเป็นมันไม่ทำงานคุณจะต้องมีการเปลี่ยนแปลงไปnp.where(np.isnan(a), a, 0) np.where(~np.isnan(a), a, 0)นี่อาจเป็นความแตกต่างในเวอร์ชันที่ใช้
TehTris

1
@TehTris คุณพูดถูกขอบคุณ ฉันเปลี่ยนb = np.where(np.isnan(a), 0, a)เป็นที่ตรงไปตรงมามากขึ้น~ตามที่ฉันคิด
Anton Protopopov


3

คุณสามารถใช้numpy.nan_to_num :

numpy.nan_to_num (x): แทนที่น่านกับศูนย์และINFกับจำนวน จำกัด

ตัวอย่าง (ดูเอกสาร):

>>> 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 ไม่เคยเท่ากับ nan

if z!=z:z=0

ดังนั้นสำหรับอาร์เรย์ 2D

for entry in nparr:
    if entry!=entry:entry=0

นี้ไม่ได้ทำงาน: entryเป็นอาร์เรย์ 1D ดังนั้นการทดสอบentry != entryไม่ให้บูลที่เรียบง่าย ValueErrorแต่ยก
Eric O Lebigot

-1

คุณสามารถใช้ฟังก์ชัน lambda ตัวอย่างสำหรับอาร์เรย์ 1D:

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

สิ่งนี้จะให้ผลลัพธ์:

[0, 2, 3]

-8

เพื่อวัตถุประสงค์ของคุณหากรายการทั้งหมดถูกจัดเก็บเป็นstrและคุณเพียงแค่ใช้การจัดเรียงตามที่คุณใช้งานจากนั้นตรวจสอบองค์ประกอบแรกและแทนที่ด้วย '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
ความคิดเห็นของคุณไม่รุนแรงไปหน่อยเหรอ? ฉันรู้ว่า numpy คืออะไร แต่รู้หรือไม่ว่าอาร์เรย์จะไม่ใช่การแสดงสตริงของตัวเลข ฉันไม่ได้ให้สิ่งนี้โดยเฉพาะจากมุมมองที่เป็นตัวเลข แต่จากมุมมองของ python หากเป็นประโยชน์
Senthil Kumaran

2
การสั่งอาร์เรย์ใหม่ดูเหมือนจะเป็นวิธีที่สับสนในการแก้ปัญหานี้
รม

ฉันต้องการรักษาลำดับของอาร์เรย์ของฉัน จะใช้ไม่ได้ถ้าคุณมี 'NaN' หลายตัวในอาร์เรย์ของคุณ
3nrique0
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.