使用IQR法去除数据集离群值后sulphates列仍存异常点问题咨询
代码问题诊断
你的代码一共存在两处问题,直接导致运行结果不符合预期:
- 拼写错误
代码中np.dhape(data)属于拼写错误,正确写法为np.shape(data),该错误运行时会直接抛出属性异常,如果你实际运行未报错,大概率是粘贴代码时的手误。 - 核心逻辑错误
这是导致sulphates列残留异常点的根本原因:
你采用的是「逐个遍历特征、每识别到当前特征的异常点就直接删除对应行」的逻辑,每次删除行之后,后续特征计算Q1、Q3、IQR的基准都是已经被修改过的数据集,而你最后验证清理效果时,箱线图的异常判定基准要么是基于原始数据集的统计值,要么和清理时的统计基准不一致,就会出现部分点在最终箱线图中被判定为异常,但清理阶段没有被识别到的情况。
举个实际场景:假设你feature_list中pH排在sulphates前面,处理pH时你删除了部分行,剩下的数据集里sulphates的分布已经发生了变化,计算得到的IQR上下限和原始数据集的上下限不同,原始数据中属于异常的点,在修改后的数据集统计规则下可能被判定为正常值,就不会被删除。
修正方案
推荐先基于原始数据集计算所有特征的异常判定阈值,再统一过滤行,避免统计基准不断变化的问题,修正后代码如下:
# 先基于原始数据集计算所有异常行的掩码 anomaly_mask = np.zeros(len(data), dtype=bool) for i in feature_list: Q1 = np.percentile(data[i], 25) Q3 = np.percentile(data[i], 75) IQR = Q3 - Q1 upper = Q3 + 1.5 * IQR lower = Q1 - 1.5 * IQR # 累计异常行 feature_anomaly = (data[i] >= upper) | (data[i] <= lower) anomaly_mask = anomaly_mask | feature_anomaly # 打印当前特征的异常点 print(f"Anomaly points in {i}:") print(np.where(feature_anomaly)) print("**************") # 统一删除所有异常行 data.drop(data.index[anomaly_mask], axis=0, inplace=True) print(f"New shape of data after removing outliers: {np.shape(data)}")
验证注意事项
清理完成后绘制箱线图时,要确保你用的是清理后的数据集绘制,异常判定规则和你清理时用的1.5倍IQR规则一致,避免出现判定基准不一致的偏差。
内容的提问来源于stack exchange,提问作者Erkys
相关产品推荐
相关产品推荐

