Python Pandas:按多列分组筛选col3出现次数Top N记录
解决Pandas分组取Top N记录的需求
嘿,我来帮你搞定这个数据处理任务!咱们一步步来,先理清楚需求:先统计每个(col1,col2,col3)组合的出现次数,再按(col1,col2)分组,每个子组里只保留col3出现次数排名前2的记录和对应的次数。
第一步:构造示例数据
首先咱们把你给出的示例数据转换成Pandas DataFrame,方便后续测试:
import pandas as pd data = [ ['A', 'x', 'p'], ['A', 'x', 'q'], ['A', 'x', 'r'], ['A', 'x', 'r'], ['A', 'y', 's'], ['A', 'y', 't'], ['A', 'z', 'u'], ['B', 'x', 'q'], ['B', 'x', 'r'], ['B', 'y', 't'] ] df = pd.DataFrame(data, columns=['col1', 'col2', 'col3'])
第二步:统计每个组合的出现次数
用groupby结合size()来统计每个(col1,col2,col3)组合的频次,然后用reset_index把分组索引转成列,并给频次列命名为count:
count_df = df.groupby(['col1', 'col2', 'col3']).size().reset_index(name='count')
这一步之后,count_df的内容如下:
| col1 | col2 | col3 | count |
|---|---|---|---|
| A | x | p | 1 |
| A | x | q | 1 |
| A | x | r | 2 |
| A | y | s | 1 |
| A | y | t | 1 |
| A | z | u | 1 |
| B | x | q | 1 |
| B | x | r | 1 |
| B | y | t | 1 |
第三步:分组取Top 2记录
这里有两种实用的方法,你可以根据自己的数据集大小选择:
方法一:用groupby.apply(直观易懂)
通过按(col1,col2)分组,对每个子组的count列降序排序,然后取前2条记录:
result = count_df.groupby(['col1', 'col2']).apply( lambda group: group.sort_values('count', ascending=False).head(2) ).reset_index(drop=True)
方法二:用rank方法(更高效,适合大数据集)
给每个子组内的count值降序排名,然后筛选出排名≤2的记录:
# 给每个分组内的count降序排名,method='first'用来处理并列情况(保留先出现的记录) count_df['rank'] = count_df.groupby(['col1', 'col2'])['count'].rank(ascending=False, method='first') # 筛选排名前2的记录,去掉rank列 result = count_df[count_df['rank'] <= 2].drop('rank', axis=1).reset_index(drop=True)
最终结果
两种方法得到的result都是你需要的格式:
| col1 | col2 | col3 | count |
|---|---|---|---|
| A | x | r | 2 |
| A | x | p | 1 |
| A | y | s | 1 |
| A | y | t | 1 |
| A | z | u | 1 |
| B | x | q | 1 |
| B | x | r | 1 |
| B | y | t | 1 |
解释一下特殊情况:比如(A,z)子组只有1条记录,所以直接保留;(B,x)子组的两个记录次数相同,所以都被保留(因为前2名就是它们)。
内容的提问来源于stack exchange,提问作者cod_rg567
相关产品推荐
相关产品推荐

