如何在Pandas中按Day分组排名时排除Total值?
问题描述
现有如下DataFrame数据:
import pandas as pd data = pd.DataFrame({'Day':['Monday','Monday','Monday','Monday','Tuesday','Tuesday','Tuesday','Tuesday'], 'City':['NY','Chicago','Miami','Total','NY','Chicago','Miami','Total'], 'Score':[100,90,70,260,120,80,90,290]})
需要按Day字段分组对Score进行排名,但排除每个分组中City为Total的行,求高效实现方法。
高效实现方案
方法一:使用groupby.transform + np.where(推荐,性能最优)
这种方法无需拆分合并数据,直接在原DataFrame上完成计算,适合大数据集场景:
import numpy as np # 对非Total行按Day分组降序排名,Total行设为NaN(可替换为'-'等自定义标记) data['Rank'] = np.where( data['City'] != 'Total', data.groupby('Day')['Score'].rank(ascending=False, method='dense'), np.nan )
- 参数说明:
ascending=False:按分数降序排名(分数越高排名越靠前),需升序可改为Truemethod='dense':采用密集排名规则(相同分数获相同排名,后续排名不跳跃),可按需替换为'min'、'max'或'first'
执行后结果示例:
| Day | City | Score | Rank |
|---|---|---|---|
| Monday | NY | 100 | 1.0 |
| Monday | Chicago | 90 | 2.0 |
| Monday | Miami | 70 | 3.0 |
| Monday | Total | 260 | NaN |
| Tuesday | NY | 120 | 1.0 |
| Tuesday | Chicago | 80 | 3.0 |
| Tuesday | Miami | 90 | 2.0 |
| Tuesday | Total | 290 | NaN |
方法二:筛选后计算排名再合并(逻辑更直观)
先过滤掉Total行计算排名,再将结果合并回原DataFrame,适合初学者理解流程:
# 筛选非Total行并计算排名 rank_df = data[data['City'] != 'Total'].assign( Rank=lambda x: x.groupby('Day')['Score'].rank(ascending=False, method='dense') ).reset_index() # 合并回原数据 data = data.merge(rank_df[['index', 'Rank']], on='index', how='left').drop('index', axis=1)
此方法逻辑清晰,但涉及数据拆分合并,性能略逊于方法一。
内容的提问来源于stack exchange,提问作者dcoolwater0502
相关产品推荐
相关产品推荐

