用numpy数组中的nan替换异常大的值

时间:2018-02-02 01:07:30

标签: python arrays numpy replace nan

我有一个数据文件中的以下列,我试图绘制。

[   2.21    2.34    2.56    2.78  180.      3.32    4.57    2.89  286.
    2.46    3.76    4.89   10.13]

所以,在我的数据集中,有时我的值会急剧增加,如(2.78 180 3.32)& (2.89 286 2.46)。我想用np.nan替换这个异常值。我试图输入这样的条件[if x(i)> 5(x(i-1)+ x(i + 1)),然后x(i)= np.nan]这意味着每当i- x的值(x是列值)比它的前一个和下一个值大得多,python将用np.nan替换该值,因此它不会被绘制或考虑。 但我还没能把它放在编码格式中。任何帮助都会非常有帮助。

import numpy as np
data=np.loadtxt('/Users/Hrihaan/Desktop/Data.txt')
x=data[:,1]
print(x)

2 个答案:

答案 0 :(得分:2)

可以针对x(i)>5(x(i-1)+x(i+1))测试条件i = 1,...,n-1,其中nx的最大允许索引。 测试所有i s的条件的矢量化版本将是:

mask = (x[1:-1] > 5*(x[2:]+x[:-2]))

然后,您可以使用以下内容将np.nan分配给mask为True的位置:

x[1:-1][mask] = np.nan

请注意,x[1:-1]slice of x - 这很重要,因为切片(与通过所谓的"advanced indexing"获得的数组相对)是原始数组的视图,{{ 1}}。因此,修改视图x会影响原始数组x[1:-1]。因此,分配到x不仅会影响切片x[1:-1][mask],还会影响x[1:-1]本身。

使用布尔掩码进行索引会调用高级索引,该索引将返回一个新数组(而不是视图)。相反,作业x不起作用,因为修改x[mask][1:-1] = np.nan不会影响x[mask]本身。 (它也不适用于更普通的原因 - x是错误的长度。)

我们试一试:

mask

为了更好地理解import numpy as np x = np.array([ 2.21, 2.34, 2.56, 2.78, 180., 3.32, 4.57, 2.89, 286., 2.46, 3.76, 4.89, 10.13]) mask = (x[1:-1] > 5*(x[2:]+x[:-2])) # array([False, False, False, True, False, False, False, True, False, # False, False], dtype=bool) x[1:-1][mask] = np.nan print(x) # array([ 2.21, 2.34, 2.56, 2.78, nan, 3.32, 4.57, 2.89, # nan, 2.46, 3.76, 4.89, 10.13]) ,有助于查看简化示例:

(x[1:-1] > 5*(x[2:]+x[:-2]))

In [57]: x = np.arange(8); x Out[57]: array([0, 1, 2, 3, 4, 5, 6, 7]) x[2:]

中删除前两项
x

In [58]: x[2:] Out[58]: array([2, 3, 4, 5, 6, 7]) x[:-2]

中删除最后两项
x
来自In [59]: x[:-2] Out[59]: array([0, 1, 2, 3, 4, 5]) 的第一个和最后一个项目的

x[1:-1]个切片:

x

NumPy算法以元素方式执行。因此In [60]: x[1:-1] Out[60]: array([1, 2, 3, 4, 5, 6]) (x[2:]+x[:-2])计算x(i-1)+x(i+1)

i=1,...,n-1

所以我们有这种情况:

In [61]: (x[2:]+x[:-2])
Out[61]: array([ 2,  4,  6,  8, 10, 12])

另一种看待它的方法是:一旦你知道条件适用于| i | x(i-1) | x(i+1) | x(i) | |-----+--------+--------+--------| | 1 | x(0) | x(2) | x(1) | | 2 | x(1) | x(3) | x(2) | | 3 | x(2) | x(4) | x(3) | | ... | | | | | n-1 | x(n-1) | x(n) | x(n-1) | |-----+--------+--------+--------| ^ ^ ^ | | | | | o--- This column is the array x[1:-1] | | | o------------ This column is the array x[2:] | o--------------------- This column is the array x[:-2] ,那么i=1,...,n-1显然会变成x(i),因为它从索引1开始并在最后一次可能之前结束1索引指数。 接下来,x[1:-1]x(i-1)可以被视为x(i+1)左侧和右侧的元素。所以我们处理的是x(i)向右移动了一个索引,向右移动了一个索引。 因此,将x[1:-1]向右移动一个索引会产生x[1:-1],向左移动x[2:]一个索引会产生x[1:-1]

顺便说一下,beautiful properties之一 Python的半开片语法是x[:-2]具有x[a:b]个元素。所以 (b-a)(相当于x[1:-1])具有x[1:n-1]个元素。注意到这一点 有2个缺少的元素使得很容易猜到相邻的数组 n-2x[1:-1]x[2:]

答案 1 :(得分:1)

如果出现异常值很少(根据定义异常= =罕见),那么使用整数索引而不是@unutbu的答案中使用的布尔索引会更有效,尤其是在大型数组中:

import numpy as np
x = np.array([ 2.21, 2.34, 2.56, 2.78, 180., 3.32, 4.57, 2.89, 286., 2.46, 3.76, 4.89, 10.13])
xp = np.pad(x, 1, 'reflect') # to deal with boundaries
idx = np.where(x > 5*(xp[2:]+xp[:-2]))
x[idx] = np.nan