如何用更Pythonic的方式交换DataFrame中同游戏的队伍值?
问题描述
现有名为original的DataFrame,结构如下:
game team 0 1 A 1 1 B 2 2 C 3 2 D ...
需求为新增一列opponent,实现每个游戏内的队伍互换,即A与B互换、C与D互换等。该DataFrame包含数千行数据、数百个唯一值,无法手动替换。
当前已实现的可行代码如下:
even_odd = [1, 2] temp = original.copy() temp['turns'] = np.tile(even_odd, len(merge2)//len(original) + 1)[:len(original)] temp = temp.sort_values(by = ['game','turns'], ascending = [True, False]).reset_index(drop=True) original['opponent'] = temp['opponent']
询问是否有Python原生函数可处理该需求,或更Pythonic的实现方式。
更Pythonic的实现方式
以下几种方法无需额外生成辅助列或复制DataFrame,逻辑更简洁高效:
方法1:groupby + shift
利用每个游戏仅包含两支队伍的特性,分组后通过位移实现互换:
original['opponent'] = original.groupby('game')['team'].shift(-1).fillna(original.groupby('game')['team'].shift(1))
逻辑说明:shift(-1)将组内下一行值移至当前行(如game=1的A对应B);组内第二行的shift(-1)会得到NaN,此时用shift(1)取上一行值填充(如B对应A),刚好完成双向互换。
方法2:groupby + transform
通过transform直接反转每个游戏组内的队伍序列:
original['opponent'] = original.groupby('game')['team'].transform(lambda x: x[::-1])
逻辑说明:每个游戏组的team列表反转后,原顺序[A,B]变为[B,A]、[C,D]变为[D,C],直接映射到新列即可,逻辑直观易懂。
方法3:索引奇偶位互换
若每个游戏的两行数据连续排列,可通过索引位运算直接映射:
import numpy as np original['opponent'] = original['team'].iloc[np.arange(len(original)) ^ 1].values
逻辑说明:np.arange(len(original)) ^ 1会将偶数索引与对应奇数索引互换(0↔1、2↔3……),直接取对应位置的team值,是三种方法中效率最高的方案。
内容的提问来源于stack exchange,提问作者MarcinKamil
相关产品推荐
相关产品推荐

