
本文介绍如何使用 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 数据一致性校验的标准实践之一。










