Pandas新增条件列:任意测量值超boxplot_stats上下须则标记缺陷
需求说明
现有存储物品测量数据的DataFrame,包含Length(长度)、Width(宽度)、Height(高度)、Operator(操作员)4个字段,样例数据如下:
Length Width Height Operator 102.67 49.53 19.69 Op-1 102.50 51.42 19.63 Op-1 95.37 52.25 21.51 Op-1 94.77 49.24 18.60 Op-1 104.26 47.90 19.46 Op-1
基于matplotlib的boxplot_stats做箱线图统计时,需要新增Status判断列:Length/Width/Height三个测量指标中任意一个值大于对应指标的whishi(箱线图上须阈值),或小于对应指标的whislo(箱线图下须阈值),该行标记为Defective,否则标记为Perfect,后续可将该列转换为0/1数值做进一步处理。
boxplot_stats返回结构及阈值取值方式示例:
from matplotlib.cbook import boxplot_stats # 调用示例 boxplot_stats(df['Height']) # 返回结果(取列表第一个元素即为对应列的统计值) [{'mean': 20.29322, 'iqr': 1.6674999999999969, 'cilo': 20.192920598732098, 'cihi': 20.4270794012679, 'whishi': 23.39, 'whislo': 17.37, 'fliers': array([], dtype=float64), 'q1': 19.475, 'med': 20.31, 'q3': 21.1425}] # 取上须阈值示例 boxplot_stats(df['Height'])[0]['whishi'] # 输出23.39
原有代码问题
两种原有实现均无法得到正确结果,核心问题如下:
- 循环逻辑错误:直接遍历DataFrame无法同时正确获取行索引、字段名和对应值;第二种实现中
apply传入的行对象用法错误,且循环判断第一个字段后就直接return,不会校验剩余两个字段。 - 运算符优先级错误:位运算符
|优先级高于比较运算符,判断条件未加括号会导致逻辑运算顺序错乱。 - 赋值逻辑错误:直接给
df['Status']整列赋值会覆盖之前所有判断结果,无法实现逐行标记。 - 性能问题:每次判断都重复调用
boxplot_stats计算阈值,数据量大时运行效率极低。
正确实现代码
from matplotlib.cbook import boxplot_stats import pandas as pd # 1. 预定义要校验的测量字段,提前计算所有字段的上下须阈值,避免重复计算 check_cols = ['Length', 'Width', 'Height'] col_threshold = {} for col in check_cols: stats_res = boxplot_stats(df[col])[0] col_threshold[col] = { "whislo": stats_res['whislo'], "whishi": stats_res['whishi'] } # 2. 初始化所有行默认状态为Perfect df['Status'] = 'Perfect' # 3. 逐字段校验,只要任意字段越界就标记为Defective for col in check_cols: lo = col_threshold[col]['whislo'] hi = col_threshold[col]['whishi'] # 布尔索引筛选越界行,更新状态,注意逻辑或两边条件加括号 df.loc[(df[col] < lo) | (df[col] > hi), 'Status'] = 'Defective' # 可选:后续转换为0/1数值标签 # df['Status_label'] = df['Status'].map({'Perfect': 0, 'Defective': 1})
实现说明
- 提前一次性计算所有字段的箱线图阈值,避免重复调用统计函数,大幅提升运行效率
- 采用pandas原生向量化布尔索引做判断,比
apply逐行循环性能高3~10倍,适配百万级以上数据集 - 逻辑符合需求:初始全部为合格状态,只要任意一个字段触发越界条件就标记为缺陷,不会漏判
- 所有逻辑判断条件加括号规避运算符优先级问题,不会出现逻辑错误
内容的提问来源于stack exchange,提问作者Gabriel Santello
相关产品推荐
相关产品推荐

