使用 numpy.argwhere 移除异常值
Removal of outliers using numpy.argwhere
大家好这个问题可能更多的是关于逻辑而不是代码,希望有人能点亮它。
所以,我有一个包含一些离群值的数据列表,我想通过使用列表中每个项目之间的差异并确定差异太大的地方来删除它。
在此示例中,我想从数据列表中删除索引 [2,3,4]。最好的方法是什么?
我曾尝试使用 np.argwhere() 方法来查找索引,但是,我被困在如何使用它的结果来切片 np.array??
data=[4.0, 4.5, 22.5, 40.5, 22.5, 3.5, 3.0, 3.5, 4.5, 3.5, 2.5]
data=np.array(data)
d = data[:-1] - data[1:]
print(np.mean(d))
在这个例子中,当我打印差异 (d) 时,它 returns 我是这样的:
print(d) # returns:[ -0.5 -18. -18. 18. 19. 0.5 -0.5 -1. 1. 1. ]
很好。现在,我应用的逻辑是指示 d 中我们的数字高于原始数据平均值的位置。
x = np.argwhere(d>np.mean(data))
print(x) # returns: array([3], dtype=int64), array([4], dtype=int64)
indices_to_extract = [x[0]-1,x[-1]]
print(indices_to_extract) # returns: [array([2], dtype=int64), array([[4]], dtype=int64)]
a1 = np.delete(r,indices_to_extract,axis=0)
print(a1) #returns: [ 4. 4.5 40.5 3.5 3. 3.5 4.5 3.5 2.5]
#Desirable return:
[ 4. 4.5 3.5 3. 3.5 4.5 3.5 2.5]
主要问题是,如何从 np.argwhere() 的数字范围中得出可用于切片的结果??
取列表项之间差异的问题在于,例如索引为 1 (4.5) 的值将被视为离群值(它因差异而获得高值)。在取差时你也可以获得正值和负值,所以如果你想这样做,你应该在差值的结果上应用模块(abs
)。
发现异常值的方法如下:
计算 z 分数:
d = (data - np.mean(data)) / np.std(data)
Select 数据中除异常值(高于 75% 分位数)外的每个值:
data[np.where( ~(d > np.quantile(d, 0.75)))]
输出:
array([4. , 4.5, 3.5, 3. , 3.5, 4.5, 3.5, 2.5])
要对一系列数字使用 np.argwhere()
在您的情况下说 [3,20]
使用:
x = np.argwhere((data<20) & (data>3))
到return数组less/greater比一个数字(比如20以下的数据)你可以简单地使用:
data[np.where(data<20)]
并且对于一系列数字说 [3,20]
:
data[np.where((data<20)&(data>3))]
我建议使用归一化到中位数的距离,这样更稳健:
d = np.abs(data - np.median(data))
mdev = np.median(d)
s = d / (mdev if mdev else 1.)
print(data[s < 4])
您可以将阈值(这里是最后一行 4
)更改为您想要的准确度。
输出:
[4. 4.5 3.5 3. 3.5 4.5 3.5 2.5]
大家好这个问题可能更多的是关于逻辑而不是代码,希望有人能点亮它。
所以,我有一个包含一些离群值的数据列表,我想通过使用列表中每个项目之间的差异并确定差异太大的地方来删除它。
在此示例中,我想从数据列表中删除索引 [2,3,4]。最好的方法是什么?
我曾尝试使用 np.argwhere() 方法来查找索引,但是,我被困在如何使用它的结果来切片 np.array??
data=[4.0, 4.5, 22.5, 40.5, 22.5, 3.5, 3.0, 3.5, 4.5, 3.5, 2.5]
data=np.array(data)
d = data[:-1] - data[1:]
print(np.mean(d))
在这个例子中,当我打印差异 (d) 时,它 returns 我是这样的:
print(d) # returns:[ -0.5 -18. -18. 18. 19. 0.5 -0.5 -1. 1. 1. ]
很好。现在,我应用的逻辑是指示 d 中我们的数字高于原始数据平均值的位置。
x = np.argwhere(d>np.mean(data))
print(x) # returns: array([3], dtype=int64), array([4], dtype=int64)
indices_to_extract = [x[0]-1,x[-1]]
print(indices_to_extract) # returns: [array([2], dtype=int64), array([[4]], dtype=int64)]
a1 = np.delete(r,indices_to_extract,axis=0)
print(a1) #returns: [ 4. 4.5 40.5 3.5 3. 3.5 4.5 3.5 2.5]
#Desirable return:
[ 4. 4.5 3.5 3. 3.5 4.5 3.5 2.5]
主要问题是,如何从 np.argwhere() 的数字范围中得出可用于切片的结果??
取列表项之间差异的问题在于,例如索引为 1 (4.5) 的值将被视为离群值(它因差异而获得高值)。在取差时你也可以获得正值和负值,所以如果你想这样做,你应该在差值的结果上应用模块(abs
)。
发现异常值的方法如下:
计算 z 分数:
d = (data - np.mean(data)) / np.std(data)
Select 数据中除异常值(高于 75% 分位数)外的每个值:
data[np.where( ~(d > np.quantile(d, 0.75)))]
输出:
array([4. , 4.5, 3.5, 3. , 3.5, 4.5, 3.5, 2.5])
要对一系列数字使用 np.argwhere()
在您的情况下说 [3,20]
使用:
x = np.argwhere((data<20) & (data>3))
到return数组less/greater比一个数字(比如20以下的数据)你可以简单地使用:
data[np.where(data<20)]
并且对于一系列数字说 [3,20]
:
data[np.where((data<20)&(data>3))]
我建议使用归一化到中位数的距离,这样更稳健:
d = np.abs(data - np.median(data))
mdev = np.median(d)
s = d / (mdev if mdev else 1.)
print(data[s < 4])
您可以将阈值(这里是最后一行 4
)更改为您想要的准确度。
输出:
[4. 4.5 3.5 3. 3.5 4.5 3.5 2.5]