从数组中删除Nan值


221

我想弄清楚如何从数组中删除nan值。我的数组看起来像这样:

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

如何从中删除nanx


明确地说,“去除NaN”是指仅过滤掉非null值的子集。不要“用某些值(零,常数,均值,中位数等)填充NaN”
smci

Answers:


360

如果您对数组使用numpy,也可以使用

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

等效地

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

[感谢chbrown新增了速记]

说明

内部函数numpy.isnan返回一个布尔值/逻辑数组,该数组在True每个地方都x具有非数字值。因为我们希望相反,我们使用逻辑不操作,~以获得与阵列True到处都是这x 一个有效的数字。

最后,我们使用此逻辑数组索引到原始数组x,仅检索非NaN值。


31
x = x[numpy.isfinite(x)]
lazy1 2012年

14
x = x[~numpy.isnan(x)],等同于mutzmatron的原始答案,但更短。如果您想保留自己的无限性numpy.isfinite(numpy.inf) == False,请当然知道这一点,但是~numpy.isnan(numpy.inf) == True
chbrown

7
对于希望使用ndarray解决此问题并保持尺寸的人们,请使用numpy,其中np.where(np.isfinite(x), x, 0)
BoltzmannBrain

1
TypeError:只能将整数标量数组转换为标量索引
6

1
@towry:发生这种情况是因为您的输入x不是numpy数组。如果要使用逻辑索引,它必须是一个数组-例如x = np.array(x)
jmetz

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

由于v!= v仅适用于NaN,因此适用于列表和numpy数组


5
这是一种hack,但在从混合类型的对象(例如字符串和nan)的对象数组中过滤nan时非常有用。
奥斯丁·理查森

非常干净的解决方案。
Moondra '17

2
这似乎很聪明,但是如果使逻辑模糊并且理论上其他对象(例如自定义类)也可以具有此属性
Chris_Rands

也很有用,因为x与类型的解决方案相对应,只需指定一次即可x[~numpy.isnan(x)]。当x由长表达式定义时,这很方便,并且您不想通过创建临时变量来存储此长表达式的结果而使代码混乱。
Christian O'Reilly

34

试试这个:

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

有关更多信息,请阅读列表理解


5
如果您使用的是numpy,则我的答案和@ lazy1的答案都比列表理解要快一个数量级-lazy1的解决方案要稍快一些(尽管从技术上讲,它也不会返回任何无穷大值)。
jmetz 2012年

不要忘了括号:)print ([value for value in x if not math.isnan(value)])
hypers

如果您使用numpy作为最佳答案,那么您可以在np软件包中使用此列表理解答案:因此,返回您的列表而不使用[value for value in x if not np.isnan(value)]
nans


6

执行以上操作:

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

要么

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

我发现重置为相同的变量(x)不会删除实际的nan值,而必须使用其他变量。将其设置为其他变量将删除nans。例如

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

这很奇怪; 根据文档,布尔数组索引(这是)处于高级索引之下,显然“总是返回数据的副本”,因此您应该x用新值覆盖(即不使用NaNs ...) 。您能否提供更多有关为什么发生这种情况的信息?
jmetz

5

如其他人所示

x[~numpy.isnan(x)]

作品。但是,如果numpy dtype不是本机数据类型(例如,如果它是object),则将引发错误。在这种情况下,您可以使用熊猫。

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

4

所述接受的答案改变为2D阵列的形状。我在这里提出了一个使用Pandas dropna()功能的解决方案。它适用于一维和二维阵列。在2D情况下,您可以选择天气删除包含的行或列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='')

结果:

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

如果您正在使用 numpy

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

# second get the values
x = x[ii]


0

这是我为NaN和infs过滤ndarray “ X”的方法,

我创建的行映射不包含NaN任何内容inf,如下所示:

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

idx是一个元组。它的第二列(idx[1])包含数组的索引,在该行中找不到NaNinf

然后:

filtered_X = X[idx[1]]

filtered_X包含X,而不 包含NaNnor inf


0

@jmetz的答案可能是大多数人需要的答案。但是,它会产生一维数组,例如,使其无法删除矩阵中的整个行或列。

为此,应将逻辑数组缩小为一维,然后索引目标数组。例如,以下内容将删除至少具有一个NaN值的行:

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

在这里查看更多详细信息

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.