Pandas 中基于多列检测行间数据一致性并标记异常

13次阅读

Pandas 中基于多列检测行间数据一致性并标记异常

本文介绍如何使用 pandes 的 `groupby().transform(‘nunique’)` 高效识别同一组(如相同国家与年份)内数值列不一致的行,并统一标记为“invalid”,适用于数据清洗与质量校验场景。

在实际数据分析中,常需校验结构化数据的一致性——例如,当多条记录具有相同的业务主键(如 Country 和 Reference Year 组合),但关键指标(如 value)却存在差异,就表明数据存在冲突或录入错误,需被标记为无效。

上述问题的核心在于:对每组 (Country, Reference Year),判断其 value 是否完全一致;若组内 value 取值数量 > 1,则整组所有行均视为“Invalid”。直接使用 == 进行逐行比较(如原尝试中的 df1[[‘Country’,…]] == df1[[‘Country’,…]])会引发广播维度错误,因为 pandas 无法对整个 DataFrame 执行行间两两比对逻辑。

正确解法是利用分组聚合 + 广播式赋值,推荐使用 transform(‘nunique’):

import pandas as pd import numpy as np  df1 = pd.DataFrame(     data=[['Afghanistan','2015','5.1'],           ['Afghanistan','2015','6.1'],           ['Bahrain','2020',''],           ['Bahrain','2020','32'],           ['Bahrain','2021','32'],           ['Bahrain','2022','32']],     columns=['Country', 'Reference Year', 'value'] )  # 标记逻辑:同组内 value 值种类数 > 1 → Invalid df1['Validity'] = np.where(     df1.groupby(['Country', 'Reference Year'])['value'].transform('nunique') > 1,     'Invalid',     'Valid' )

执行后输出如下:

Country Reference Year value Validity 0  Afghanistan           2015   5.1  Invalid 1  Afghanistan           2015   6.1  Invalid 2      Bahrain           2020        Invalid 3      Bahrain           2020    32  Invalid 4      Bahrain           2021    32    Valid 5      Bahrain           2022    32    Valid

关键说明

  • transform(‘nunique’) 会为每组返回该组 value 的唯一值个数,并自动广播至组内每一行,结果与原始 DataFrame 行数对齐;
  • 字符串 ” 与 ’32’ 被视为不同值(nunique=2),因此第2、3行被正确标记为 Invalid;
  • 若需将空值(” 或 NaN)视作缺失并忽略参与比较,可先做预处理:df1[‘value’] = df1[‘value’].replace(”, np.nan),再进行 transform。

⚠️ 注意事项

  • nunique 默认跳过 NaN,若字段含空字符串需显式替换,否则会影响去重逻辑;
  • 此方法时间复杂度为 O(n),远优于手动双循环apply,适合中大型数据集;
  • 若需进一步定位冲突值,可附加列:df1[‘conflict_values’] = df1.groupby([‘Country’, ‘Reference Year’])[‘value’].transform(Lambda x: ‘;’.join(x.unique()))。

该方案简洁、向量化、可读性强,是 Pandas 数据一致性校验的标准实践之一。

text=ZqhQzanResources