Pandas按对局分组匹配最高分 为DataFrame新增winner列
问题:pandas按对局分组填充胜者列
我有一个存储桌游 Terraforming Mars 对局数据的DataFrame,计划使用pandas完成多项统计计算。该DataFrame包含不同计分规则对应的累计分数字段,以及Game(对局ID)、Player(玩家ID)、Coportation(所选企业)等属性字段,示例结构与数据如下:
列名信息:
>>> df.columns Index(['Date', 'Game', 'Player', 'Coportation', 'TR', 'MILESTONES', 'AWARDS', 'CARDS', 'GREENERY', 'CITIES+G', 'Total'], dtype='object')
字段类型信息:
>>> df.dtypes Date object Game int64 Player int64 Coportation object TR int64 MILESTONES int64 AWARDS int64 CARDS int64 GREENERY int64 CITIES+G int64 Total int64 dtype: object
头部样例数据:
>>> df.head() Date Game Player Coportation ... CARDS GREENERY CITIES+G Total 0 NaN 3 1 NaN ... 41 2 3 90 1 NaN 3 2 NaN ... 6 8 9 78 2 NaN 3 3 NaN ... 26 5 11 90 3 NaN 4 1 NaN ... 44 6 2 97 4 NaN 4 2 NaN ... 22 8 2 77
需要实现的常规统计需求包括:
- 单局最高总分
- 单局最低总分
- 对局平均得分
- 玩家个人历史最高分
- 玩家个人历史最低分
- 胜场最多玩家
- 负场最多玩家
- 表现最佳企业
- 表现最差企业
当前需要先完成「胜场最多玩家」的前置步骤:为每个Game(对局)新增winner列,实现逻辑为:
- 遍历每一局游戏,获取该局
Total列最高分对应的Player值 - 将该
Player值填充到该局所有行的winner列中
逐行apply写if判断的方案无法覆盖分组取最大值对应字段的场景,需要可行实现方法。
回答
不需要写显式循环逐行处理,用pandas内置的分组变换逻辑1行代码就能实现,核心是用groupby + transform按对局分组直接广播最大值对应的玩家ID。
基础实现代码
# 按对局分组,找到每局Total最高的行对应的Player,广播填充到同组所有行 df['winner'] = df.groupby('Game')['Total'].transform(lambda x: df.loc[x.idxmax(), 'Player'])
逻辑说明
groupby('Game')会把所有行按对局ID拆分为独立分组,每个分组对应同一局的所有玩家数据- 对每个分组的
Total列执行transform操作:x.idxmax()会返回当前分组里总分最高的行的索引,用该索引取对应行的Player值就是该局胜者 transform会自动把计算出的胜者值对齐填充到该分组的每一行,不需要手动写循环匹配
平局场景适配
如果遇到样例中Game=3两个玩家同拿90分的平局场景,上面的代码默认取索引更靠前的玩家作为胜者。如果需要标记平局,可以调整逻辑:
def get_winner(group): max_total = group['Total'].max() winners = group[group['Total'] == max_total]['Player'].tolist() # 单胜者返回玩家ID,多胜者返回平局标记 return winners[0] if len(winners) == 1 else 'tie' df['winner'] = df.groupby('Game').apply(get_winner).loc[df['Game']].values
后续胜场统计参考
胜者列填充完成后,胜场统计直接按玩家去重计数即可,避免同一局多行重复计数:
win_counts = df.drop_duplicates(subset=['Game', 'winner'])['winner'].value_counts() top_winner = win_counts.idxmax()
内容的提问来源于stack exchange,提问作者DrakeMurdoch
相关产品推荐
相关产品推荐

