检测损坏数据的算法?

时间:2015-08-29 08:00:15

标签: python algorithm pandas

我不确定这是否是正确的地方,所以请原谅我,如果这个声音不相关的话。这是我的情况:

我的数据集及时为continual,我需要处理一些errones data。与邻居相比,它们的价值突然增加。

这是数据集的一部分。如您所见,第4个值(28.3)突然增加。 (值在最后一栏)

19741212,0700,200,1,N,  4.6
19741212,0800,190,1,N,  4.6
19741212,0900,180,1,N,  5.7
19741212,1000,160,1,N, 28.3   # wrong data, need interpolate from neighbors
19741212,1100,170,1,N,  4.6
19741212,1200,200,1,N,  5.1
19741212,1300,230,1,N,  5.1

我需要identify他们,然后从附近的数据中interpolate替换它们。我想知道现有algorithm是否存在?

如果我从头开始实施一种方法,我就会伤害:

  1. 从近数据点计算增量
  2. 选择适当的阈值以检测损坏的数据
  3. 但是我不确定这是否足够好,也许我忽略了其他部分,这会导致大量的误报。

    另外,我使用PythonPandas来处理数据,因此相关资源会很棒。

2 个答案:

答案 0 :(得分:2)

检测损坏数据或异常值的一种方法是首先计算一系列的滚动中位数(它对异常值的鲁棒性),然后计算实际观测值与滚动中位数之间的距离。过滤掉距离大于阈值的观察结果。

# your data
# ====================================
print(df)


             A    B  C  D     E
19741212   700  200  1  N   4.6
19741212   800  190  1  N   4.6
19741212   900  180  1  N   5.7
19741212  1000  160  1  N  28.3
19741212  1100  170  1  N   4.6
19741212  1200  200  1  N   5.1
19741212  1300  230  1  N   5.1

# roling median, 3-term moving windows
# =================================================
res = pd.rolling_median(df['E'], window=3, center=True)
print(res)

19741212    NaN
19741212    4.6
19741212    5.7
19741212    5.7
19741212    5.1
19741212    5.1
19741212    NaN
dtype: float64

# threshold 20% from rolling median
threshold = 0.2
mask = abs(df['E'] - res)/res > threshold
# replace outliers with rolling medians
df.loc[mask, 'E'] = res[mask]

print(df)

             A    B  C  D    E
19741212   700  200  1  N  4.6
19741212   800  190  1  N  4.6
19741212   900  180  1  N  5.7
19741212  1000  160  1  N  5.7
19741212  1100  170  1  N  4.6
19741212  1200  200  1  N  5.1
19741212  1300  230  1  N  5.1

答案 1 :(得分:1)

您还可以识别ouliers,您可以测试它们与平均值的距离并设置标准差阈值。

根据https://stackoverflow.com/a/11686764/2477491,您可以使用以下内容将异常值设置为NaN:

def reject_outliers(data, m=2): # 2 is the std treshold, fit for your needs.
    return data[abs(data - np.mean(data)) < m * np.std(data)]

data[6] = reject_outliers(data[5]) # creates a new column with outliers set to Nan

          0     1    2  3  4     5    6  
0  19741212   700  200  1  N   4.6  4.6  
1  19741212   800  190  1  N   4.6  4.6  
2  19741212   900  180  1  N   5.7  5.7  
3  19741212  1000  160  1  N  28.3  NaN  
4  19741212  1100  170  1  N   4.6  4.6  
5  19741212  1200  200  1  N   5.1  5.1  
6  19741212  1300  230  1  N   5.1  5.1  

如果你的系列有趋势,你可能宁愿将它应用于时间移动窗口而不是整个系列。

关于在窗口上应用自定义函数,我通常使用scipy.ndimage.filters.generic_filter也可以使用1d数组,并返回在脚印定义的移动窗口上应用函数的标量。下面是一个关于如何仅在1x3足迹中插入NaN的平均值的示例:

from scipy import ndimage as im

def interpNan(win): # with win the 1x3 window
    if win[1] != win[1]: # if center of footprint is a nan
        return round(np.nanmean(win), 1)
    else:
        return round(win[1], 1)

footprint  = np.array([1,1,1])
data[7]    = im.generic_filter(data[6], interpNan, footprint = footprint )

          0     1    2  3  4     5    6    7
0  19741212   700  200  1  N   4.6  4.6  4.6
1  19741212   800  190  1  N   4.6  4.6  4.6
2  19741212   900  180  1  N   5.7  5.7  5.7
3  19741212  1000  160  1  N  28.3  NaN  5.2
4  19741212  1100  170  1  N   4.6  4.6  4.6
5  19741212  1200  200  1  N   5.1  5.1  5.1
6  19741212  1300  230  1  N   5.1  5.1  5.1

[7行x 8列]

您还可以合并这两个函数,但是对于质量分析,我并不总是保留原始数据,有效数据和插值数据。