你能解释一下异常值过滤吗?

Could you explain outliers filtering?

我有一个包含先验离群值的 DataFrame。我想至少从“降雨量”变量中删除异常值。我这样做如下。它看起来有效,但我在第二个数字中仍然有异常值。 正常吗?

  1. 移除异常值之前

  1. 移除异常值
rainfall = df["Rainfall"]
q3 = np.quantile(rainfall, 0.75)
q1 = np.quantile(rainfall, 0.25)

iqr = q3 - q1

upper_bound = q1 + 1.5 * iqr
lower_bound = q3 - 1.5 * iqr

rainfall_wo_outliers = df[(rainfall <= lower_bound) | (rainfall >= upper_bound)]["Rainfall"]
  1. 去除异常值后

Ps:我之前用MinMaxScaler

缩放过数据

首先,你去除异常值的条件是倒置的,你应该使用(rainfall >= lower_bound) & (rainfall <= upper_bound)

现在回到最基本的问题。 是的,这很正常。异常值移除(至少使用您的方法)依赖于当前分布四分位数来计算 IQR 并决定删除哪些点。

然而,一旦你删除数据,新的人口有新的统计参数,这意味着你最终会得到新的异常值,相对于 新的 Q1,和 Q3.

这对于正常或均匀数据尤其明显:

import numpy as np
import matplotlib.pyplot as plt

def iqr_outliers_removal(s):
    q1, q3 = np.quantile(s, [0.25, 0.75])
    iqr = q3 - q1
    upper_bound = q1 + 1.5 * iqr
    lower_bound = q3 - 1.5 * iqr
    
    return s[(s>=lower_bound) & (s<=upper_bound)]

# generate random data
s = np.random.normal(size=10_000)

# iteratively remove outliers
s2 = s.copy()
n = len(s2)
out = [s2]
for _ in range(100):
    print('.', end='')
    s2 = iqr_outliers_removal(s2)
    out.append(s2)
    
ax = plt.subplot()
ax.plot(list(map(len, out)), marker='.', ls='')
ax.set_ylabel('data size')
ax.set_xlabel('iteration')
ax.set_yscale('log')

100 次异常值移除迭代的样本大小:

现在,您可能会删除异常值并且新的人口变得稳定。如果您多次使用 s = np.random.uniform(size=10_000) 和 运行 模拟,有时您可能会得到类似这样的结果:

但这只是偶然;)