如何高效统计DataFrame各分组中独属该组的唯一值数量?
高效统计DataFrame分组中独有的唯一值数量
这是个非常实用的需求,我来分享几个比你当前分步操作更高效简洁的实现方式,完全利用pandas的向量化操作提升性能,尤其适合数据量较大的场景:
方法一:先定位独有value,再分组统计
思路是先找出所有仅出现在单个label组中的value,再回到原数据按label统计这些value的数量:
import pandas as pd test_df = pd.DataFrame({ 'label': [1, 1, 1, 1, 2, 2, 3, 3, 3], 'value': [0, 0, 1, 2, 1, 2, 2, 3, 4] }) # 1. 统计每个value对应的不同label数量,筛选出仅属于一组的value value_label_unique_count = test_df.drop_duplicates().groupby('value')['label'].nunique() exclusive_values = value_label_unique_count[value_label_unique_count == 1].index # 2. 筛选出独有value,去重后按label分组计数,补全缺失的label并填充0 result = ( test_df[test_df['value'].isin(exclusive_values)] .drop_duplicates(['label', 'value']) .groupby('label')['value'] .count() .reset_index(name='uni_val') .merge(test_df['label'].unique(), on='label', how='right') .fillna(0) .astype({'uni_val': int}) ) print(result)
输出结果完全符合你的预期:
label uni_val 0 1 1 1 2 0 2 3 2
这个方法的优势是先通过去重减少计算量,再利用nunique()快速定位独有value,全程都是pandas的内置分组操作,比手动遍历分组的unique列表去对比效率高得多。
方法二:用transform简化标记逻辑
可以用transform把每个value的分组唯一性标记到每一行,再直接统计,代码更紧凑:
import pandas as pd test_df = pd.DataFrame({ 'label': [1, 1, 1, 1, 2, 2, 3, 3, 3], 'value': [0, 0, 1, 2, 1, 2, 2, 3, 4] }) # 给每行标记对应的value是否只属于一个label组 test_df['is_exclusive'] = test_df.groupby('value')['label'].transform('nunique') == 1 # 筛选出独有value,去重后分组计数,用reindex补全所有label并填充0 result = ( test_df[test_df['is_exclusive']] .drop_duplicates(['label', 'value']) .groupby('label')['value'] .count() .reindex(test_df['label'].unique(), fill_value=0) .reset_index(name='uni_val') ) print(result)
这个方法用transform将分组计算的结果广播到每一行,逻辑更直观,代码行数更少,同样能高效得到目标结果。
对比你原来的方法,这两种方式都避免了手动处理每个分组的unique列表,利用pandas的向量化操作大幅提升了效率,同时代码更简洁易维护。
内容的提问来源于stack exchange,提问作者HassanAboueisha




