【问题标题】:Detecting outliers in a DataFrame column with small value changes in pandas检测熊猫值变化很小的DataFrame列中的异常值
【发布时间】:2018-08-22 14:19:07
【问题描述】:

我正在处理一个列,该列的值应该在行之间有微小的变化。这些值是物理测量值,由于环境因素,测量值可能不正确,连续样本之间的增量非常高。变化率是一个被视为问题输入的量,因为可以对其进行更改以适应这种异常值检测的精度需求。

检测方法可以计算到目前为止看到的值的平均值并将异常值标记为高于给定变化率的值,或者检查行之间的值变化并标记距离较大的索引值比变化率和指数值,其中返回的值相对于标记为异常值之前的第一个值低于可接受的变化率。第一种方法可能更难,因为应该从正确的值计算平均值,也就是说,标记为异常值的值不应该考虑到平均值的计算中。

正确的解决方案应该返回指示异常值的索引列表,然后将其用于将相应的值设置为 f.e. NaN 或使用插值方法填充这些值。

例子

df = pd.DataFrame({'small_changing': [5.14, 5.18, 5.22, 5.18, 5.20, 5.17, 5.25, 5.55, 5.62, 5.78, 6.21, 6.13, 5.71, 5.35, 5.29, 5.24, 5.16, 5.18, 5.20, 5.15, 5.17, 5.00, 4.96, 4.88, 4.71, 4.65, 4.73, 4.79, 4.89, 4.92, 5.05, 5.11, 5.14, 5.17, 5.22, 5.24, 5.18, 5.20]})

假设0.15 的变化率有两个异常值组要检测,假设第二种检测方法考虑了行之间的差异。

第一组对应索引值[7, 12],因为67的行之间的差异是0.3,高于0.15的限制,而行之间的差异@ 987654331@ 和130.113 行是第一行,其差异在0.15 限制内。

第二组对应索引值[21, 29],因为2021的行之间的差异是0.17,高于0.15的限制,而行之间的差异@ 987654341@ 和300.1230 行是第一行,其差异在0.15 限制内。

此示例的结果:[7, 8, 9, 10, 11, 12, 21, 22, 23, 24, 25, 26, 27, 28, 29]

【问题讨论】:

    标签: python pandas dataframe outliers


    【解决方案1】:

    希望对你有帮助。

    我认为它不是 Pythonic,但它有效:

    def outlier_detection(points, limit):
        outliers_index = list()
        k=0
        for i in range(0,len(points)-1):
            if abs(points[i-k] - points[i+1]) >= limit:
                k+=1
                outliers_index.append(i+1)
            else:
                k=0
        return outliers_index
    
    outlier_detection(df['small_changing'].values, 0.15)
    
    OUT: [7, 8, 9, 10, 11, 12, 21, 22, 23, 24, 25, 26, 27, 28, 29]
    

    【讨论】:

      【解决方案2】:

      这可能会节省大型数据集上稀疏分布的异常值的时间 -

      def df_outlier(df, threshold=0.15):
          column = df.columns[0]
          df["outlier"] = False
          df_difference = df.copy()
          df_difference["difference"] = abs(df[column] - df[column].shift(1)).shift(-1)
          df_difference = df_difference.loc[df_difference["difference"] > threshold]
          for index in df_difference.index:
              row = df.loc[index]
              if not row["outlier"]:
                  df_check = df[index+1:].copy()
                  df_check["a_difference"] = abs(df_check[column] - row[column])
                  df_check.loc[df_check["a_difference"] > threshold, "outlier"] = True
                  df.loc[((df.index >= df_check.index[0]) & (df.index < df_check["outlier"].ne(True).idxmax())), "outlier"] = True
      
          return list(df.loc[df["outlier"] == True].index)
      

      我正在使用这个。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2013-02-10
        • 2022-01-07
        • 2013-12-21
        • 2018-03-16
        • 2019-09-15
        • 2018-06-10
        • 2020-09-23
        相关资源
        最近更新 更多