【问题标题】:Outlier removal techniques from an array数组中的异常值去除技术
【发布时间】:2022-01-15 08:08:54
【问题描述】:

我知道网上有大量资源可用于去除异常值,但我还没有设法获得我真正想要的东西,所以在这里发帖,我有一个 4 列的数组(或 DF)。现在我想根据列的异常值从 DF 中删除行。以下是我尝试过的,但它们并不完美。

def outliers2(data2, m = 4.5):
    c=[]
    data = data2[:,1] # Choosing the column
    d = np.abs(data - np.median(data)) # deviation comoutation
    mdev = np.median(d) # mean deviation
    for i in range(len(data)):
        if (abs(data[i] - mdev) < m * np.std(data)):
            c.append(data2[i])            
    return c

x = pd.DataFrame(outliers2(np.array(b)))
column = ['t','orig_w','filt_w','smt_w']
x.columns = column

#Plot
plt.rcParams['figure.figsize'] = [10,8]
plt.plot(b.t,b.orig_w,'o',label='Original',alpha=0.8) # Original
plt.plot(x.t,x.orig_w,'.',c='r',label='Outlier removed',alpha=0.8) # After outlier removal
plt.legend()

该图说明了结果的外观,蓝色原始点上的异常值处理后的红色点。我真的很想摆脱 x~0 标记周围的那些垂直点组。怎么办?

此处提供了指向数据文件的链接:Full data 绿色圆圈通常显示我想摆脱的点

【问题讨论】:

  • 你能再发一张包围异常值的图片吗?

标签: python pandas numpy scipy outliers


【解决方案1】:

你可以使用scipy's median_filter:

import pandas as pd
from matplotlib import pyplot as plt
from scipy.ndimage import median_filter

b = pd.read_csv("test.csv")

x = b.copy()
x.orig_w = median_filter(b.orig_w, size=15)

#Plot
plt.rcParams['figure.figsize'] = [10,8]
#Original
plt.plot(b.t,b.orig_w,'o',label='Original',alpha=0.8) 
# After outlier removal
plt.plot(x.t,x.orig_w,'.',c='r',label='Outlier removed',alpha=0.8) 
plt.legend()
plt.show()

示例输出:

【讨论】:

    【解决方案2】:

    由于您的数据看起来是正弦曲线,因此使用滑动窗口执行异常值删除技术可能很有意义。您可以计算您正在测试的点的直接邻域中的中位数和标准差,并通过检查您的点是否在与您的中位数标准差的指定数量内来检查它是否是异常值。此方法以Hampel filter 的名义存在(更多详细信息herehere)。下面是一种实现它的方法,窗口大小等于每侧 50 个样本,阈值基于 1.25 标准:

    import numpy as np
    import pandas as pd
    import matplotlib.pyplot as plt
    
    df_orig=pd.read_csv('trial_data.csv')
    
    def hampel_filter(df_orig, m = 1.25,win=50):
      c=[]
      k = 1.4826 
      for i in range(len(df_orig)):
    
          med=np.median(df_orig['orig_w'][np.amax([0,i-win]):np.amin([len(df_orig['orig_w']),i+win])])
          mad=np.std(np.abs(df_orig['orig_w'][np.amax([0,i-win]):np.amin([len(df_orig['orig_w']),i+win])]-med))
          sigma=k*mad
          
          if np.abs(med-df_orig['orig_w'][i])<m*sigma:
              c.append(df_orig.loc[i])            
      return c
    
    x = pd.DataFrame(hampel_filter(df_orig))
    column = ['t','orig_w','filt_w','smt_w']
    x.columns = column
    
    #Plot
    plt.rcParams['figure.figsize'] = [10,8]
    plt.plot(df['t'],df['orig_w'],'o',label='Original',alpha=0.8) # Original
    plt.plot(x.t,x.orig_w,'.',c='r',label='Outlier removed',alpha=0.8) # After outlier removal
    plt.legend()
    
    

    输出给出:

    然后您可以微调 winm 以获得适合您的结果。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-05-21
      • 1970-01-01
      • 2021-05-03
      • 1970-01-01
      • 1970-01-01
      • 2022-06-23
      • 2019-12-25
      相关资源
      最近更新 更多