使用百分位数去除Pandas DataFrame异常值时遇逻辑问题求助
解决Pandas中用百分位数去除异常值时的逻辑问题
嘿,我猜你遇到的逻辑问题大概率是处理完特征列后没法关联回原有的id和label,或者是训练集/测试集的过滤逻辑不一致导致的数据泄露——毕竟你同时传入了训练和测试数据,这两个点是新手用百分位过滤异常值时最容易踩的坑。我来帮你把代码捋顺并修正:
修正后的完整代码
def processing_data(train_data, test_data): # 第一步:明确要处理的特征列(排除id和label) feature_cols = train_data.columns.drop(['id', 'label']) # 第二步:仅用训练集计算百分位数(核心!避免测试集数据泄露) low_percentile = 0.05 high_percentile = 0.95 quantile_bounds = train_data[feature_cols].quantile([low_percentile, high_percentile]) # 第三步:定义通用过滤函数,保留所有特征在百分位区间内的样本 def filter_outliers(df): # 对每个特征生成「是否在区间内」的布尔掩码 feature_mask = df[feature_cols].apply( lambda col: col.between( quantile_bounds.loc[low_percentile, col.name], quantile_bounds.loc[high_percentile, col.name] ), axis=0 ) # 要求样本的所有特征都符合条件(行内全为True才保留) final_mask = feature_mask.all(axis=1) # 返回包含id和label的完整过滤后数据 return df[final_mask] # 第四步:分别过滤训练集和测试集 cleaned_train = filter_outliers(train_data) cleaned_test = filter_outliers(test_data) return cleaned_train, cleaned_test
关键逻辑说明(帮你避开之前的坑)
- 不提前移除id/label:直接在原数据框上用掩码过滤,这样id和label会自动和过滤后的特征列对应,不会丢失关联关系。之前你先移除这两列再处理,很容易导致后续无法把标识列加回去。
- 训练集单独计算百分位:绝对不能用测试集的数据参与百分位数计算,否则属于数据泄露——测试集必须完全模拟真实场景,用训练集学到的规则来过滤。
- 逐特征校验+全特征达标:
apply会对每个特征单独判断是否在区间内,all(axis=1)确保只有所有特征都正常的样本才被保留(如果你的业务允许单个特征异常的样本保留,可以把all改成any,但一般异常值过滤都是要求全特征正常)。
额外的优化建议
- 如果某些特征不需要过滤异常值,可以在
feature_cols里手动排除它们,比如feature_cols = train_data.columns.drop(['id', 'label', '不需要过滤的列名']) - 百分位数阈值可以根据业务调整:如果0.05/0.95去掉的数据太多,试试0.01/0.99;如果还是有异常值,可以考虑用四分位距(IQR)方法结合百分位使用。
内容的提问来源于stack exchange,提问作者DreamerP
相关产品推荐
相关产品推荐

