chuyển đổi giá trị nan thành 0


95

Tôi có một mảng 2D numpy. Một số giá trị trong mảng này là NaN. Tôi muốn thực hiện các hoạt động nhất định bằng cách sử dụng mảng này. Ví dụ, hãy xem xét mảng:

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

Tôi đang cố gắng lấy từng hàng, từng hàng một, sắp xếp nó theo thứ tự đảo ngược để nhận được tối đa 3 giá trị từ hàng và lấy giá trị trung bình của chúng. Mã tôi đã thử là:

# 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

Điều này không hoạt động đối với các hàng có chứa NaN. Câu hỏi của tôi là, có cách nào nhanh chóng để chuyển đổi tất cả các NaNgiá trị thành 0 trong mảng 2D numpy để tôi không gặp vấn đề với việc sắp xếp và những thứ khác mà tôi đang cố gắng thực hiện không.


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

@kirilloid: nghe hay đấy, còn cách sử dụng ví dụ thì sao?
serv-inc

Câu trả lời:


124

Điều này sẽ hoạt động:

from numpy import *

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

Trong trường hợp trên where_are_NaNs là:

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

139

AMảng 2D của bạn ở đâu :

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

Hàm isnantạo ra một mảng bool cho biết vị trí của các NaNgiá trị. Một mảng boolean có thể được sử dụng để lập chỉ mục một mảng có cùng hình dạng. Hãy coi nó như một chiếc mặt nạ.


40

Còn nan_to_num () thì sao?


11
nan_to_num () cũng thay đổi số nguyên - điều này có thể không mong muốn trong một số trường hợp.
Agos

11
Nó cũng chậm hơn 10 lần so với các phương pháp khác.
user48956

7
Tôi không chắc về câu lệnh tat "> 10x slow" nên tôi đã kiểm tra. Thật vậy, nó là chậm hơn nhiều. Cảm ơn vì đã chỉ ra điều này.
Gabriel

16

Bạn có thể sử dụng np.wheređể tìm nơi bạn có 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
vì nó không hoạt động, bạn cần phải thay đổi np.where(np.isnan(a), a, 0)thành np.where(~np.isnan(a), a, 0). Điều này có thể là một sự khác biệt trong các phiên bản được sử dụng.
TehTris

1
@TehTris bạn nói đúng, cảm ơn. Tôi đã thay đổi nó thành b = np.where(np.isnan(a), 0, a)đơn giản hơn sau đó theo ~như tôi nghĩ.
Anton Protopopov


3

Bạn có thể sử dụng numpy.nan_to_num :

numpy.nan_to_num (x): Thay nan bằng 0inf bằng số hữu hạn .

Ví dụ (xem tài liệu):

>>> 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 không bao giờ bằng nan

if z!=z:z=0

vì vậy đối với một mảng 2D

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

Điều này không hoạt động: entrylà một mảng 1D, vì vậy bài kiểm tra entry != entrykhông đưa ra một boolean đơn giản nhưng tăng lên ValueError.
Eric O Lebigot

-1

Bạn có thể sử dụng hàm lambda, một ví dụ cho mảng 1D:

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

Điều này sẽ cho bạn kết quả:

[0, 2, 3]

-8

Đối với mục đích của bạn, nếu tất cả các mục được lưu trữ strvà bạn chỉ sử dụng được sắp xếp như bạn đang sử dụng và sau đó kiểm tra phần tử đầu tiên và thay thế nó bằng '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
Không phải là bình luận của bạn hơi khắc nghiệt? Tôi biết numpy là gì, nhưng biết rằng mảng sẽ không phải là chuỗi biểu diễn các số. Tôi đặc biệt không xem xét điều này từ góc độ numpy mà từ góc độ của python, nếu điều đó hữu ích.
Senthil Kumaran

2
Sắp xếp lại mảng nghe có vẻ là một cách khó hiểu để giải quyết vấn đề này.
holografix

Tôi cần bảo toàn thứ tự mảng của mình. Nó sẽ không hoạt động nếu bạn có nhiều 'NaN' trong mảng của mình.
3nrique0
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.