如何从Pandas DataFrame中筛选阈值外数值并基于1.5倍IQR提取异常值
问题修正
你原来的代码存在3个核心逻辑错误:
- 遍历对象错误:
for x in s遍历的是DataFrame的列名,不是x列的数值 - 没有限定分组:筛选异常值时没有过滤对应
subset分组的数据,会统计到其他分组的数值 - 判断逻辑错误:
s[s.x >= higher_range]返回的是DataFrame对象,直接放在if判断中会触发Pandas报错
按你要求的for循环实现版本
import matplotlib.pyplot as plt import seaborn as sns import numpy as np import pandas as pd plt.style.use('seaborn') s = pd.read_csv('NormalSample.csv') def iqrmult(s, subset): # 提前提取对应分组的x列数据,避免重复过滤 group_data = s[s.group == subset]['x'] q1 = group_data.quantile(q=.25) q3 = group_data.quantile(q=.75) iqr = q3 - q1 iqrmultiplier = iqr * 1.5 lower_range = q1 - iqrmultiplier higher_range = q3 + iqrmultiplier lower_outliers = [] upper_outliers = [] # 遍历当前分组的x数值做判断 for val in group_data: if val < lower_range: lower_outliers.append(val) elif val > higher_range: upper_outliers.append(val) print('IQR值为: ', iqr) print('异常值下阈值为: ', lower_range) print('异常值上阈值为: ', higher_range) print('下侧异常值共{}个,具体为: '.format(len(lower_outliers)), lower_outliers) print('上侧异常值共{}个,具体为: '.format(len(upper_outliers)), upper_outliers) iqrmult(s, 0)
更高效的Pandas向量化写法(无循环,适合大数据量)
如果没有强制要求用for循环,用Pandas原生布尔索引筛选的效率更高,千行级数据可以毫秒级出结果:
def iqrmult(s, subset): group_data = s[s.group == subset]['x'] q1 = group_data.quantile(0.25) q3 = group_data.quantile(0.75) iqr = q3 - q1 lower_range = q1 - 1.5*iqr higher_range = q3 + 1.5*iqr lower_outliers = group_data[group_data < lower_range].tolist() upper_outliers = group_data[group_data > higher_range].tolist() print('IQR值为: ', iqr) print('异常值下阈值为: ', lower_range) print('异常值上阈值为: ', higher_range) print('下侧异常值共{}个,具体为: '.format(len(lower_outliers)), lower_outliers) print('上侧异常值共{}个,具体为: '.format(len(upper_outliers)), upper_outliers)
内容的提问来源于stack exchange,提问作者Schultzie67
相关产品推荐
相关产品推荐

