You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Pandas:按gameId分组后关联生成related_player列

问题描述

我有一个约一万行的DataFrame,数据示例如下:

import pandas as pd
import numpy as np
data = {'gameId': [1, 1, 1, 1, 1, 2, 2, 2, 2, 2], 
        'eventId': [1, 2, 3, 4, 5, 1, 2, 3, 4, 5], 
        'player': ['A', 'B', 'C', 'D', 'E', 'A', 'B', 'C', 'D', 'E'], 
        'related_eventId': [2, 1, 4, 3, np.nan, 2, 1, 4, 3, np.nan]}
df = pd.DataFrame(data)

需要生成名为related_player的列,该列的值为同gameId分组下,eventId与当前行related_eventId相等的行对应的player值。

之前无gameId分组时,可以用merge实现:

result = df.merge(df[['eventId', 'player']], left_on='related_eventId', right_on='eventId', how='left', suffixes=('', '_related'))
result.rename(columns={'player_related': 'related_player', 'eventId_related': 'related_eventId'}, inplace=True)
result = result[['eventId', 'player', 'related_eventId', 'related_player']]

但加入gameId分组后,上述方法无法得到正确结果,求Pandas中的正确实现方式。

预期输出如下:

gameIdeventIdplayerrelated_eventIdrelated_player
11A2B
12B1A
13C4D
14D3C
15ENaNNaN
21A2B
22B1A
23C4D
24D3C
25ENaNNaN
解决方案

方法1:多键Merge(最直观高效)

直接在merge时同时匹配gameId和related_eventId,确保关联的是同分组内的eventId对应数据:

# 准备用于关联的临时表,保留分组、事件ID和玩家信息
lookup = df[['gameId', 'eventId', 'player']]

# 多键匹配merge
result = df.merge(
    lookup,
    left_on=['gameId', 'related_eventId'],
    right_on=['gameId', 'eventId'],
    how='left',
    suffixes=('', '_related')
)

# 整理列名和结构
result = result.rename(columns={'player_related': 'related_player'}).drop(columns='eventId_related')

该方法逻辑清晰,一万行数据的处理效率完全够用。

方法2:GroupBy + 分组内映射

按gameId分组后,在每个分组内构建eventId到player的字典映射,再匹配related_eventId:

def add_related_player(group):
    # 构建当前分组内的事件ID-玩家映射
    event_player_map = group.set_index('eventId')['player'].to_dict()
    # 映射关联事件对应的玩家
    group['related_player'] = group['related_eventId'].map(event_player_map)
    return group

# 分组应用处理函数
result = df.groupby('gameId', group_keys=False).apply(add_related_player)

这种方式更贴合分组逻辑,代码可读性强,适合理解分组内的匹配规则。

方法3:多层索引映射(简洁写法)

先构建(gameId, eventId)为键的多层索引映射,再通过组合键匹配:

# 构建分组+事件ID到玩家的映射
mapping = df.set_index(['gameId', 'eventId'])['player']

# 每行用(gameId, related_eventId)作为键查找对应玩家
df['related_player'] = df.apply(lambda x: mapping.get((x['gameId'], x['related_eventId'])), axis=1)

写法简洁,但apply的效率略低于前两种方法,不过一万行数据完全可以正常运行。


内容的提问来源于stack exchange,提问作者Delopera

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.07 10:22:46