自定义异常值移除函数未完全清理异常值且后续调用报KeyError问题
解决KNN填充后逐列移除异常值的KeyError与未完全删除问题
问题根源分析
- KeyError 原因:
你用np.where拿到的是数据的整数位置索引,但pd.DataFrame.drop()默认按标签索引删除行。第一次调用函数处理ph列后,non_null_rows的行标签已不连续(部分行被删除),此时用原位置对应的标签去删除,就会出现找不到索引的错误(比如2189行已被删掉)。 - 异常值未完全移除:
函数中先删upper异常值再删lower,但删除upper后数据集已变化,而lower的索引仍基于原数据集计算,导致部分lower异常值未被正确识别删除。
修复后的函数代码
import numpy as np import seaborn as sns import matplotlib.pyplot as plt import pandas as pd def remove_outliers(dataset, col_name, raw_data): # 计算IQR上下界 Q1 = dataset[col_name].quantile(0.25) Q3 = dataset[col_name].quantile(0.75) IQR = Q3 - Q1 lower_bound = Q1 - 1.5 * IQR upper_bound = Q3 + 1.5 * IQR # 布尔索引一次性筛选正常数据,避免索引混乱 mask = (dataset[col_name] >= lower_bound) & (dataset[col_name] <= upper_bound) cleaned_dataset = dataset[mask].copy() cleaned_dataset = cleaned_dataset.reset_index(drop=True) # 绘制箱线图对比 plt.figure(figsize=(10, 0.5)) sns.boxplot(raw_data[col_name], orient="h").set(xlabel=f"{col_name} raw data") plt.show() plt.figure(figsize=(10, 0.5)) sns.boxplot(cleaned_dataset[col_name], orient="h").set(xlabel=f"{col_name} no outliers") plt.show() return cleaned_dataset
改动说明
- 用布尔掩码一次性筛选:避免分两次
drop导致的索引不匹配,确保异常值被完整过滤。 - 传入原始数据集
raw_data绘图:避免依赖全局变量,函数逻辑更独立。 - 提前
copy()数据集:避免对原数据集的意外修改,保证每轮处理的独立性。
调用方式
# 处理ph列 non_null_rows = remove_outliers(non_null_rows, 'ph', H2O_data) # 处理Hardness列 non_null_rows = remove_outliers(non_null_rows, 'Hardness', H2O_data)
这样调用后,既不会触发KeyError,也能完整移除每列的异常值。
内容的提问来源于stack exchange,提问作者Pompilia
相关产品推荐
相关产品推荐

