基于Pandas按volt_id分组检测DataFrame中的电压值异常行
按分组检测电压数据中的异常行
嘿,这个按组检测异常值的需求太常见啦!用Pandas就能非常优雅地搞定,我来给你一步步演示具体实现方式~
我们这里用Z-score(标准分数)+ 3σ原则来判断异常——简单来说,就是判断组内数据是否偏离均值超过3倍标准差,这是工业界常用的异常检测方法,你也可以根据业务需求调整阈值(比如改成2倍标准差)。
步骤1:准备环境与示例数据
先导入Pandas和NumPy,然后构造你给出的示例数据集:
import pandas as pd import numpy as np # 构造示例数据集 data = { 'time': [14, 15, 15, 16, 17, 14, 16, 20], 'volt_id': ['A', 'A', 'B', 'B', 'B', 'C', 'C', 'C'], 'value': [300.00, 310.00, 200.00, 210.00, 300.00, 100.00, 110.00, 200.00] } df = pd.DataFrame(data)
步骤2:按组计算统计量并标记异常
我们用groupby结合transform,把每组的均值、标准差广播到每一行,再计算Z-score判断是否异常:
# 按volt_id分组,计算每组的均值和标准差,添加到原数据 df['group_mean'] = df.groupby('volt_id')['value'].transform('mean') df['group_std'] = df.groupby('volt_id')['value'].transform('std') # 计算Z-score:(当前值 - 组均值) / 组标准差 df['z_score'] = (df['value'] - df['group_mean']) / df['group_std'] # 筛选出异常行(这里用Z-score绝对值>3作为阈值,可按需调整) outliers = df[np.abs(df['z_score']) > 3]
步骤3:查看结果(附示例数据的计算说明)
针对你给出的示例数据:
- 组A的均值是305,标准差≈7.07,两个值的Z-score分别是-0.707和0.707,都在正常范围;
- 组B的均值≈236.67,标准差≈50.33,300的Z-score≈1.26,未超过阈值;
- 组C的均值≈136.67,标准差≈50.33,200的Z-score≈1.26,也未超过阈值;
所以示例数据里没有符合“3倍标准差”的异常行,但如果你的实际数据有极端值,就会被精准筛选出来。
更优雅的极简写法
如果你不想在原数据框里保留中间列,也可以用一行代码直接得到异常行:
outliers = df[ df.groupby('volt_id')['value'] .transform(lambda x: np.abs((x - x.mean()) / x.std()) > 3) ]
这种写法省去了中间列的生成,直接通过分组转换完成筛选,非常简洁高效~
内容的提问来源于stack exchange,提问作者Joohun Lee
相关产品推荐
相关产品推荐

