循环迭代移除DataFrame异常值问题求助
迭代移除DataFrame异常值的逻辑问题
我有一个DataFrame,需要循环迭代提取并移除其中的异常值:每次移除异常值后重新检查新的DataFrame,若仍存在异常值则继续移除,以此类推。但目前仅能移除首次出现的异常值,无法将后续异常值与之前的合并后从原始数据中一并移除,代码逻辑肯定有问题。
原始DataFrame:
import pandas as pd df = pd.DataFrame({'Date': ['01-01-2022','02-01-2022','03-01-2022','04-01-2022','05-01-2022','06-01-2022','07-01-2022','08-01-2022','09-01-2022','10-01-2022','11-01-2022','12-01-2022','13-01-2022','14-01-2022','15-01-2022','16-01-2022','17-01-2022','18-01-2022','19-01-2022','20-01-2022'], 'Value': [100,50,60,3,85,15,250,97,150,25,49,64,88,35,154,73,67,48,52,90]})
预期效果:
- 第一次循环排除第6行(值:250)
- 第二次循环排除第8行(值:150)和第14行(值:154)
- 最终得到无异常值的DataFrame
使用的代码:
outlier = [] df2 = [] while True: Q1 = df['Value'].quantile(0.25) Q3 = df['Value'].quantile(0.75) IQR = Q3 - Q1 Lower_Limit = Q1 - 1.5 * IQR Upper_Limit = Q3 + 1.5 * IQR outliers = df['Value'][((df['Value'] < Lower_Limit)|(df['Value'] > Upper_Limit))] outlier.append(outliers) df = df['Value'][~((df['Value'] < Lower_Limit)|(df['Value'] > Upper_Limit))] df2.append(df) Q1 = pd.DataFrame(df2).quantile(0.25) Q3 = pd.DataFrame(df2).quantile(0.75) IQR = Q3 - Q1 Lower_Limit = Q1 - 1.5 * IQR Upper_Limit = Q3 + 1.5 * IQR outliers = pd.DataFrame(df2)[((pd.DataFrame(df2) < Lower_Limit) | (pd.DataFrame(df2) > Upper_Limit))].dropna() outlier.append(outliers) df2 = pd.DataFrame(df2)[~((pd.DataFrame(df2) < Lower_Limit) |(pd.DataFrame(df2) > Upper_Limit))] df2.append(df2) break
当前输出:
print('df before Removing Outliers: ' + str(len(df))) print('df After Removing Outliers: ' + str(len(df2))) print('Number of outliers: ' + str(len(outlier))) print('Max outlier value: '+ str(outlier.max())) print('Min outlier value: '+ str(outlier.min())) # 输出结果 df before Removing Outliers: 20 df After Removing Outliers: 17 Number of outliers: 3 Max outlier value: 250 Min outlier value: 150
问题分析与修复代码
原代码核心问题
- 循环逻辑失效:
while True仅执行一次就break,完全没实现迭代检查;中途把df转成Series,丢失了Date列和原始索引,无法准确追踪异常值。 - 数据结构混乱:
df2初始为列表,中途强行转DataFrame,导致数据格式错乱,无法正确迭代更新。 - 异常值收集逻辑错误:重复计算IQR且逻辑重叠,异常值未按原始数据统一归集。
修复后的代码
import pandas as pd # 原始数据 df = pd.DataFrame({'Date': ['01-01-2022','02-01-2022','03-01-2022','04-01-2022','05-01-2022','06-01-2022','07-01-2022','08-01-2022','09-01-2022','10-01-2022','11-01-2022','12-01-2022','13-01-2022','14-01-2022','15-01-2022','16-01-2022','17-01-2022','18-01-2022','19-01-2022','20-01-2022'], 'Value': [100,50,60,3,85,15,250,97,150,25,49,64,88,35,154,73,67,48,52,90]}) # 保留原始数据副本,用于最终移除所有异常值 original_df = df.copy() all_outliers = pd.DataFrame(columns=df.columns) while True: # 计算当前DataFrame的IQR和上下限 Q1 = df['Value'].quantile(0.25) Q3 = df['Value'].quantile(0.75) IQR = Q3 - Q1 lower_limit = Q1 - 1.5 * IQR upper_limit = Q3 + 1.5 * IQR # 找出当前的异常值 current_outliers = df[(df['Value'] < lower_limit) | (df['Value'] > upper_limit)] # 如果没有异常值,终止循环 if current_outliers.empty: break # 收集异常值 all_outliers = pd.concat([all_outliers, current_outliers]) # 移除当前异常值,更新DataFrame df = df[~((df['Value'] < lower_limit) | (df['Value'] > upper_limit))] # 从原始数据中移除所有收集到的异常值 final_df = original_df[~original_df.index.isin(all_outliers.index)] # 打印结果 print('原始数据行数: ' + str(len(original_df))) print('移除异常值后行数: ' + str(len(final_df))) print('异常值总数: ' + str(len(all_outliers))) print('异常值最大值: '+ str(all_outliers['Value'].max())) print('异常值最小值: '+ str(all_outliers['Value'].min())) print('\n所有异常值:') print(all_outliers) print('\n最终无异常值的DataFrame:') print(final_df)
修复后效果
- 第一次循环识别并收集值为250的异常行
- 第二次循环更新IQR后,识别并收集值为150和154的异常行
- 第三次循环检查无异常值,终止循环
- 最终从原始数据中一次性移除所有异常值,保留完整的Date列和正确数据结构
内容的提问来源于stack exchange,提问作者Mahmoud Badr
相关产品推荐
相关产品推荐

