如何基于指定列计数筛选Pandas DataFrame行并合并小类别
问题描述
我有一个包含分类数据的Pandas DataFrame,对其中某列执行value_counts()后得到如下结果:
HR 176 Coding 81 Reject 74 Database Administration 21 Finance 17 Project Management 16 Sales 15 DevOps 13 Core Electronics 10 Networking 10 Medical Science 9 Core Mechanical 8 Web Development 4 Puzzles 3 behavioural 3 not a question 2 civil engineering 1 Mathematics 1 Finance, Medical Science 1 Sales, HR 1
希望保留计数≥阈值(如10)的类别,其余小类别合并为*Other*,预期结果如下:
HR 176 Coding 81 Reject 74 *Other* 33 Database Administration 21 Finance 17 Project Management 16 Sales 15 DevOps 13 Core Electronics 10 Networking 10
此前我通过defaultdict(int)实现了该功能,想了解是否有Pandas的标准实现方式。
Pandas标准实现方式
有几种简洁的Pandas原生方法可以实现这个需求,以下是常用方案:
方案1:where+groupby组合
先获取value_counts的结果(假设命名为counts),用where保留符合阈值的类别,其余替换为*Other*后重新聚合:
import pandas as pd # 假设原始value_counts结果为counts counts = df['目标列名'].value_counts() threshold = 10 # 核心处理逻辑 result = counts.where(counts >= threshold, '*Other*') \ .groupby(level=0).sum() # 若要保持原类别排序(仅将*Other*追加到末尾),可调整为: mask = counts >= threshold other_total = counts[~mask].sum() result = pd.concat([counts[mask], pd.Series([other_total], index=['*Other*'])])
方案2:replace+groupby组合
先构建类别映射字典,将小于阈值的类别统一映射为*Other*,再聚合统计:
threshold = 10 # 生成映射规则:达标类别保留原名,否则映射为*Other* category_map = {cat: cat if counts[cat] >= threshold else '*Other*' for cat in counts.index} result = counts.rename(category_map).groupby(level=0).sum()
方案3:直接从原始DataFrame处理
如果不想先单独计算value_counts,可以直接对原始DataFrame操作:
threshold = 10 # 先筛选出需要保留的类别 keep_categories = df['目标列名'].value_counts()[lambda x: x >= threshold].index # 替换小类别为*Other*后统计 result = df['目标列名'].where(df['目标列名'].isin(keep_categories), '*Other*').value_counts()
这些方法都是Pandas原生实现,无需依赖defaultdict,代码更简洁且符合Pandas的惯用风格。
内容的提问来源于stack exchange,提问作者Abirbhav G.
相关产品推荐
相关产品推荐

