Loại bỏ các giá trị nan từ một mảng


223

Tôi muốn tìm ra cách loại bỏ các giá trị nan khỏi mảng của tôi. Mảng của tôi trông giống như thế này:

x = [1400, 1500, 1600, nan, nan, nan ,1700] #Not in this exact configuration

Làm thế nào tôi có thể loại bỏ các nangiá trị từ x?


Để rõ ràng, bằng cách "loại bỏ NaN", bạn có nghĩa là chỉ lọc ra tập hợp con của các giá trị không null . Không "điền vào NaN với một số giá trị (không, không đổi, trung bình, trung bình, v.v.)"
smci

Câu trả lời:


362

Nếu bạn đang sử dụng numpy cho mảng của mình, bạn cũng có thể sử dụng

x = x[numpy.logical_not(numpy.isnan(x))]

Tương đương

x = x[~numpy.isnan(x)]

[Cảm ơn chbrown cho tốc ký thêm]

Giải trình

Hàm bên trong, numpy.isnantrả về một mảng boolean / logic có giá trị Trueở mọi nơi xkhông phải là số. Như chúng ta muốn ngược lại, chúng ta sử dụng toán tử không logic, ~để lấy một mảng có Trues ở mọi nơi x số hợp lệ.

Cuối cùng, chúng tôi sử dụng mảng logic này để lập chỉ mục vào mảng ban đầu x, để chỉ truy xuất các giá trị không phải NaN.


31
Hoặcx = x[numpy.isfinite(x)]
lazy1

14
Hoặc x = x[~numpy.isnan(x)], tương đương với câu trả lời ban đầu của mutzmatron, nhưng ngắn hơn. Trong trường hợp bạn muốn giữ sự vô tận của mình, hãy biết rằng numpy.isfinite(numpy.inf) == False, tất nhiên, nhưng ~numpy.isnan(numpy.inf) == True.
chbrown

8
Đối với những người đang tìm cách giải quyết vấn đề này bằng một ndarray và duy trì kích thước, hãy sử dụng numpy trong đó :np.where(np.isfinite(x), x, 0)
BoltzmannBrain

1
TypeError: chỉ các mảng vô hướng nguyên có thể được chuyển đổi thành một chỉ số vô hướng
kéo theo

1
@towry: điều này xảy ra bởi vì đầu vào của bạn, xkhông phải là một mảng numpy. Nếu bạn muốn sử dụng chỉ mục hợp lý, nó phải là một mảng - ví dụx = np.array(x)
jmetz

50
filter(lambda v: v==v, x)

hoạt động cả cho danh sách và mảng numpy vì v! = v chỉ dành cho NaN


5
Một hack nhưng một đặc biệt hữu ích trong trường hợp bạn đang lọc các ô từ một mảng các đối tượng với các kiểu hỗn hợp, chẳng hạn như một chuỗi và các ô.
Austin Richardson

Dung dịch rất sạch.
Moondra

2
Điều này có vẻ thông minh, nhưng nếu che khuất logic và các đối tượng khác về mặt lý thuyết (như các lớp tùy chỉnh) cũng có thể có thuộc tính này
Chris_Rands

Cũng hữu ích vì nó chỉ cần xđược chỉ định một lần trái ngược với các giải pháp của loại x[~numpy.isnan(x)]. Điều này thuận tiện khi xđược xác định bởi một biểu thức dài và bạn không muốn làm lộn xộn mã bằng cách tạo một biến tạm thời để lưu trữ kết quả của biểu thức dài này.
Christian O'Reilly

34

Thử cái này:

import math
print [value for value in x if not math.isnan(value)]

Để biết thêm, đọc trên Danh sách toàn diện .


5
Nếu bạn đang sử dụng numpy cả câu trả lời của tôi và bởi @ lazy1 gần như là một thứ tự cường độ nhanh hơn mức hiểu danh sách - giải pháp của lazy1 nhanh hơn một chút (mặc dù về mặt kỹ thuật cũng sẽ không trả về bất kỳ giá trị vô cực nào).
jmetz

Đừng quên dấu ngoặc :)print ([value for value in x if not math.isnan(value)])
hypers

Nếu bạn đang sử dụng numpy như câu trả lời hàng đầu thì bạn có thể sử dụng câu trả lời thấu hiểu danh sách này với npgói: Vì vậy, trả về danh sách của bạn mà không cần nans:[value for value in x if not np.isnan(value)]
yeliabsalohcin 23/11/18

23

Đối với tôi, câu trả lời của @jmetz không hiệu quả, tuy nhiên sử dụng gấu trúc isnull () đã làm.

x = x[~pd.isnull(x)]

6

Làm như trên:

x = x[~numpy.isnan(x)]

hoặc là

x = x[numpy.logical_not(numpy.isnan(x))]

Tôi thấy rằng việc đặt lại cùng một biến (x) không loại bỏ các giá trị nan thực tế và phải sử dụng một biến khác. Đặt nó vào một biến khác đã loại bỏ các nans. ví dụ

y = x[~numpy.isnan(x)]

Điều này thật kỳ lạ; theo các tài liệu , lập chỉ mục mảng boolean (đây là), được lập chỉ mục nâng cao , dường như "luôn trả về một bản sao của dữ liệu", vì vậy bạn nên ghi xđè lên giá trị mới (tức là không có NaNs ...) . Bạn có thể cung cấp thêm thông tin về lý do tại sao điều này có thể xảy ra?
jmetz

5

Như được hiển thị bởi những người khác

x[~numpy.isnan(x)]

làm. Nhưng nó sẽ đưa ra một lỗi nếu dtype numpy không phải là kiểu dữ liệu nguyên gốc, ví dụ nếu nó là đối tượng. Trong trường hợp đó bạn có thể sử dụng gấu trúc.

x[~pandas.isna(x)] or x[~pandas.isnull(x)]

4

Các câu trả lời được chấp nhận thay đổi hình dạng cho mảng 2ngày. Tôi trình bày một giải pháp ở đây, sử dụng chức năng Pandas dropna () . Nó hoạt động cho mảng 1D và 2D. Trong trường hợp 2D, bạn có thể chọn thời tiết để thả hàng hoặc cột chứa np.nan.

import pandas as pd
import numpy as np

def dropna(arr, *args, **kwarg):
    assert isinstance(arr, np.ndarray)
    dropped=pd.DataFrame(arr).dropna(*args, **kwarg).values
    if arr.ndim==1:
        dropped=dropped.flatten()
    return dropped

x = np.array([1400, 1500, 1600, np.nan, np.nan, np.nan ,1700])
y = np.array([[1400, 1500, 1600], [np.nan, 0, np.nan] ,[1700,1800,np.nan]] )


print('='*20+' 1D Case: ' +'='*20+'\nInput:\n',x,sep='')
print('\ndropna:\n',dropna(x),sep='')

print('\n\n'+'='*20+' 2D Case: ' +'='*20+'\nInput:\n',y,sep='')
print('\ndropna (rows):\n',dropna(y),sep='')
print('\ndropna (columns):\n',dropna(y,axis=1),sep='')

print('\n\n'+'='*20+' x[np.logical_not(np.isnan(x))] for 2D: ' +'='*20+'\nInput:\n',y,sep='')
print('\ndropna:\n',x[np.logical_not(np.isnan(x))],sep='')

Kết quả:

==================== 1D Case: ====================
Input:
[1400. 1500. 1600.   nan   nan   nan 1700.]

dropna:
[1400. 1500. 1600. 1700.]


==================== 2D Case: ====================
Input:
[[1400. 1500. 1600.]
 [  nan    0.   nan]
 [1700. 1800.   nan]]

dropna (rows):
[[1400. 1500. 1600.]]

dropna (columns):
[[1500.]
 [   0.]
 [1800.]]


==================== x[np.logical_not(np.isnan(x))] for 2D: ====================
Input:
[[1400. 1500. 1600.]
 [  nan    0.   nan]
 [1700. 1800.   nan]]

dropna:
[1400. 1500. 1600. 1700.]

3

Nếu bạn đang sử dụng numpy

# first get the indices where the values are finite
ii = np.isfinite(x)

# second get the values
x = x[ii]


0

Đây là cách tiếp cận của tôi để lọc ndarray "X" cho NaN và infs,

Tôi tạo một bản đồ các hàng mà không có bất kỳ NaNvà bất kỳ infnhư sau:

idx = np.where((np.isnan(X)==False) & (np.isinf(X)==False))

idx là một tuple. Cột thứ hai ( idx[1]) chứa các chỉ mục của mảng, trong đó không có NaN cũng như inf được tìm thấy trên hàng.

Sau đó:

filtered_X = X[idx[1]]

filtered_Xchứa X mà không NaN hay inf.


0

Câu trả lời của @ jmetz có lẽ là câu hỏi mà nhiều người cần nhất; tuy nhiên, nó mang lại một mảng một chiều, ví dụ như làm cho nó không thể sử dụng để loại bỏ toàn bộ hàng hoặc cột trong ma trận.

Để làm như vậy, người ta nên giảm mảng logic xuống một chiều, sau đó lập chỉ mục cho mảng mục tiêu. Chẳng hạn, những điều sau đây sẽ xóa các hàng có ít nhất một giá trị NaN:

x = x[~numpy.isnan(x).any(axis=1)]

Xem thêm chi tiết tại đây .

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.