查找数据中非常大的跳转

时间:2015-05-21 06:30:57

标签: python numpy outliers

我只需要找到非常大的跳跃,这样我就可以找到簇,然后再找到噪声。样本数据如下:

0.000000
0.000500
0.001500
0.003000
0.005500
0.008700
0.012400
0.000000
0.000500
0.001500
0.003000
0.005500
0.008700
0.012400
0.000000
0.000500
0.001500
0.003000
0.005500
0.008700
0.012400
0.000000
0.000500
0.001500
0.003000
0.005500
0.008700
0.012400
0.000000
0.000500
0.001500
0.003000
0.005500
0.008700
0.012400
0.000000
0.000500
0.001500
0.003000
0.005500
0.008700
0.012400
0.012400

我需要在python中执行此操作,但也欢迎使用任何通用算法。

我已经尝试了

  1. 找到每对连续点之间的距离。
  2. 找出连续距离的比率。
  3. 找出连续比率的接近程度。
  4. 我遇到的问题是当我使用比较函数numpy.allclose()时,它的近似因子是静态的,并且对于不同程度的跳跃,它会停止工作并产生误报和漏报。

    数据可视化的一些图表。每个底部图表是总点数。 enter image description here enter image description here enter image description here

3 个答案:

答案 0 :(得分:6)

首先,您应该想象您的问题,以便更好地了解正在发生的事情:

import matplotlib.pyplot as plt
data = (0.000000, 0.000500, 0.001500, 0.003000, 0.005500, 0.008700,
        0.012400, 0.000000, 0.000500, 0.001500, 0.003000, 0.005500,
        0.008700, 0.012400, 0.000000, 0.000500, 0.001500, 0.003000,
        0.005500, 0.008700, 0.012400, 0.000000, 0.000500, 0.001500,
        0.003000, 0.005500, 0.008700, 0.012400, 0.000000, 0.000500,
        0.001500, 0.003000, 0.005500, 0.008700, 0.012400, 0.000000,
        0.000500, 0.001500, 0.003000, 0.005500, 0.008700, 0.012400, 
        0.012400)
plt.scatter(range(len(data)), data)

Scatter plot of data

其次,您需要实施步骤检测,这在wiki上有详细描述:http://en.wikipedia.org/wiki/Step_detection

选择一种您认为最适合的方法并随意使用。

更新

只是想一想:如果您的所有数据看起来与您的示例相似,您也可以尝试制作一个锯齿波(http://en.wikipedia.org/wiki/Sawtooth_wave)最小二乘(http://en.wikipedia.org/wiki/Least_squares)来找到&#34 ;跳转&#34 ;.这可以作为进一步分析的起点。

答案 1 :(得分:1)

如果您以这种方式“手动”计算接近程度,则您的方法有效:

import numpy as np
data = np.array([0.000000, 0.000500, 0.001500, 0.003000, 0.005500, 0.008700,
        0.012400, 0.000000, 0.000500, 0.001500, 0.003000, 0.005500,
        0.008700, 0.012400, 0.000000, 0.000500, 0.001500, 0.003000,
        0.005500, 0.008700, 0.012400, 0.000000, 0.000500, 0.001500,
        0.003000, 0.005500, 0.008700, 0.012400, 0.000000, 0.000500,
        0.001500, 0.003000, 0.005500, 0.008700, 0.012400, 0.000000,
        0.000500, 0.001500, 0.003000, 0.005500, 0.008700, 0.012400, 
        0.012400])
steps = data[1:] - data[:-1]
ratios = 1. * steps[1:] / steps[:-1]
jumps = ratios[1:] - ratios[:-1]
largest_jumps = np.max(jumps)
print largest_jumps

>> 3.31102877071

答案 2 :(得分:0)

这没什么特别的,但你可以尝试一下。使用向前,向后差异,您可以检测单个异常值。如果多个异常值存在于一起,它将在复杂情况下失败,但对于简单的情况,它可能会起作用:

import numpy as np
x = np.arange(20)    
# Synthetic data
sample = np.random.randn(20)
# Synthetic noise
sample[np.random.randint(0, 20, 5)] += np.random.randn(5) * 100

plot(x, sample, 'o')

enter image description here

前进和后退衍生物(它们的绝对值,因为我们关心差异的大小而不是方向):

d1 = np.r_[0, np.abs(sample[1:] - sample[:-1])]
d2 = np.r_[np.abs(sample[1:] - sample[:-1]), 0]

使用阈值屏蔽内点(它们至少有另一个节点关闭):

mask = (d1 < 5) | (d2 < 5)

显示结果:

plot(x[mask], samples[mask], 'o')

示例的硬编码5可以替换为meanmedian + std或其他内容。

再一次,并不是一种花哨的东西,正如@septi指出的那样,异常检测中有很多理论,没有简单的方法可以解决每一个问题。有关详细信息,请查看我认为适合您的问题的density based outlier deetection

enter image description here