检测DataFrame列中的离群值,其中熊猫的值变化很小

时间:2018-08-22 14:19:08

标签: python pandas dataframe outliers

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

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

正确的解决方案应返回指示异常值的索引列表,然后将其用于将相应值设置为f。 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]})

enter image description here

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

第一组对应于索引值[7, 12],因为行67之间的差为0.3,高于{{1} }限制,并且行0.156之间的差为13,行0.1是第一行,其差在13限制之内。 / p>

第二组对应于索引值0.15,因为行[21, 29]20之间的差为21,比{{1} }限制,并且行0.170.15之间的差为20,行30是第一行,其差在0.12限制之内。 / p>

此示例的结果:30

2 个答案:

答案 0 :(得分:3)

我希望这会有所帮助。

我认为它不是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]

答案 1 :(得分:0)

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

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)

我正在使用它。