如何高效获取DataFrame中对应最短耗时的‘最佳玩家’列?
更简便的实现方案(支持扩展到更多玩家)
当然有更简洁且可维护的方法!你的嵌套np.where写法在玩家数量增加到6个时,会变得非常冗长且容易出错。下面提供两种更优雅的方案,尤其适合扩展场景:
方法一:利用idxmin+字典映射(最简洁)
这种方法核心是先找到每行最小时间对应的时间列名,再通过预先定义的映射关系转换成玩家名,代码量少且扩展性极强:
import pandas as pd import numpy as np # 原始DataFrame df = pd.DataFrame({ 'Player one':["Juul","RGB10","Holi2","Combo"], 'Time play1':[13,21,15,4], 'Player two':["Jar21","helen3","Dimi","kanh"], 'Time play2':[5,7,19,4], 'Player three':["josi","Mae","Dylen","Joe18"], 'Time play3':[4,12,8,66,] }) # 1. 定义时间列到玩家列的映射字典(扩展到6个玩家时,只需添加键值对) time_to_player = { 'Time play1': 'Player one', 'Time play2': 'Player two', 'Time play3': 'Player three' } # 2. 获取所有时间列 time_cols = list(time_to_player.keys()) # 3. 找到每行最小时间对应的时间列名,再映射成玩家名 min_time_col = df[time_cols].idxmin(axis=1) df["Best player"] = min_time_col.map(time_to_player)
运行后得到的结果和你的原始代码完全一致,而且当玩家数量增加到6个时,只需要在time_to_player里新增3组键值对即可,无需修改核心逻辑。
方法二:重塑DataFrame(更灵活,支持多最小时间场景)
如果需要处理多个玩家时间相同的情况(比如想返回所有耗时最短的玩家),可以先把宽格式的DataFrame转成窄格式,再分组处理:
# 1. 定义玩家列和时间列 player_cols = ['Player one', 'Player two', 'Player three'] time_cols = ['Time play1', 'Time play2', 'Time play3'] # 2. 重塑数据:将每行的玩家和对应时间配对 temp = pd.DataFrame({ 'player': df[player_cols].values.flatten(), 'time': df[time_cols].values.flatten(), 'original_index': np.repeat(df.index, len(player_cols)) }) # 3. 按原始行分组,找到时间最小的玩家(若有多个,用逗号分隔) best_players = temp.groupby('original_index').apply( lambda x: ', '.join(x[x['time'] == x['time'].min()]['player']) ) # 4. 赋值回原DataFrame df['Best player'] = best_players
这种方法的优势是可以灵活处理多值场景,比如第四行有两个玩家耗时都是4,会返回Combo, kanh,而不是只取第一个。
为什么这两种方法更优?
- 可扩展性:玩家数量从3个增加到6个时,只需修改映射字典或列名列表,无需嵌套多层判断
- 可读性:代码逻辑清晰,比嵌套
np.where更容易理解和维护 - 灵活性:方法二可以轻松适配多最小时间的需求
内容的提问来源于stack exchange,提问作者Enrique Salazar
相关产品推荐
相关产品推荐

