IQR异常值检测通过Q3−Q1界定正常范围,适合单变量连续型数据且对偏态、长尾分布鲁棒;ZScore依赖正态假设易受异常值干扰而误判;二者组合应分阶段使用:先IQR粗筛强离群点,再在清洗后数据上用ZScore检测中度异常。
IQR异常值检测,它适合什么场景IQR(四分位距)通过计算数据的上四分位数 Q3 与下四分位数 Q1 的差值来定义正常范围,异常值被定义为小于 Q1 - 1.5 * IQR 或大于 Q3 + 1.5 * IQR 的点。它不依赖数据服从正态分布,对偏态、长尾或含极端离群点的数据鲁棒性更强。
实操建议:
n 时,Q1/Q3 估计不稳定,慎用
numpy.quantile() 而非 pd.Series.quantile(),前者默认插值更稳定import numpy as np data = np.array([1, 2, 2, 3, 4, 5, 5, 6, 7, 8, 100]) q1 = np.quantile(data, 0.25) q3 = np.quantile(data, 0.75) iqr = q3 - q1 lower_bound = q1 - 1.5 * iqr upper_bound = q3 + 1.5 * iqr outliers = data[(data < lower_bound) | (data > upper_bound)] print(outliers) # [100]
ZScore基于均值和标准差标准化数据,将值转换为“距离均值几个标准差”,通常以 abs(z) > 3 作为异常阈值。但它隐含假设数据近似服从正态分布——一旦存在未被识别的异常值,它们会拉高 std、扭曲 mean,导致其他本该被标记的点逃逸检测。
常见错误现象:
scipy.stats.zscore() 但未设 axis=0,在二维数组上沿错误轴计算std ≈ 0 导致除零或无限大实操建议:
n )改用 scipy.stats.ttest_1samp 的t统计量替代Z
label_encoded 类别)使用ZScorefrom scipy import stats data = np.array([1, 2, 2, 3, 4, 5, 5, 6, 7, 8, 100]) z_scores = np.abs(stats.zscore(data)) outliers = data[z_scores > 3] print(outliers) # [] ← 这里就漏掉了100
单独用IQR易漏掉“温和但持续偏离”的异常(如缓慢漂移的传感器偏差),单独用ZScore易受污染均值影响。二者组合不是简单取并集,而是分阶段利用各自优势。
推荐流程:
|x| > Q3+1.5×IQR 或 ),临时掩码剔除
2 )
"high_confidence_outlier")注意:不要在原始数据上同时计算两个指标再按“任一触发即报警”,这会导致重复告警且无法区分异常强度。
异常检测不是跑完函数就结束,落地时真正卡住进度的往往是这些细节:
Q1 可能来自未来时段groupby().apply() 而非全局统计,否则不同群体的量纲差异会被抹平IQR 和 std 的变化率;若某天 std 突增200%,大概率是上游数据源异常,而非业务异常