如何用Pandas/Numpy在分组内将每行数据追加到组内所有行?
赛马数据集行转列分组处理问题
我有一个按raceId分组的赛马数据集,单场比赛的数据示例如下:
data_orig = { 'meetingId': [178515] * 6, 'raceId': [879507] * 6, 'horseId': [90001, 90002, 90003, 90004, 90005, 90006], 'position': [1, 2, 3, 4, 5, 6], 'weight': [51, 52, 53, 54, 55, 56], }
需要将组内每行的马匹专属数据追加到组内的每一行,预期结果如下:
data_new = { 'meetingId': [178515] * 6, 'raceId': [879507] * 6, 'horseId_a':[90001, 90002, 90003, 90004, 90005, 90006], 'position_a':[1, 2, 3, 4, 5, 6], 'weight_a':[51, 52, 53, 54, 55, 56], 'horseId_b':[90002, 90003, 90004, 90005, 90006, 90001], 'position_b':[2, 3, 4, 5, 6, 1], 'weight_b':[52, 53, 54, 55, 56, 51], 'horseId_c':[90003, 90004, 90005, 90006, 90001, 90002], 'position_c':[3, 4, 5, 6, 1, 2], 'weight_c':[53, 54, 55, 56, 51, 52], 'horseId_d':[90004, 90005, 90006, 90001, 90002, 90003], 'position_d':[4, 5, 6, 1, 2, 3], 'weight_d':[54, 55, 56, 51, 52, 53], 'horseId_e':[90005, 90006, 90001, 90002, 90003, 90004], 'position_e':[5, 6, 1, 2, 3, 4], 'weight_e':[55, 56, 51, 52, 53, 54,], 'horseId_f':[90006, 90001, 90002, 90003, 90004, 90005], 'position_f':[6, 1, 2, 3, 4, 5], 'weight_f':[56, 51, 52, 53, 54, 55], }
我尝试了以下代码但未成功:
data_orig_df = pd.DataFrame(data_orig) new_df = pd.DataFrame() for index, row_i in data_orig_df.iterrows(): horseId = row_i['horseId'] row_new = row_i.copy() for index, row_j in race_df.iterrows(): if row_j['horseId']: continue row_new = pd.merge(row_new, row_j[getHorseSpecificCols()], suffixes=('', row_j['position'])) new_df = pd.concat([new_df, row_new], axis=1)
解决方案
核心思路是对每组内的马匹数据进行循环移位,生成对应后缀的列后合并到原数据中,具体实现代码如下:
import pandas as pd # 原始数据转DataFrame df = pd.DataFrame(data_orig) # 定义需要处理的马匹专属列 horse_cols = ['horseId', 'position', 'weight'] # 生成后缀列表(对应6匹马的后缀a到f) suffixes = ['a', 'b', 'c', 'd', 'e', 'f'] # 按raceId分组处理(多场比赛时自动独立处理每组) def process_group(g): # 保留原始赛事标识列 result = g[['meetingId', 'raceId']].copy() # 循环生成每一组移位后的列 for i, suffix in enumerate(suffixes): # 循环移位:i=0不移位,i=1向上移1行,末尾缺失用开头数据填充 shifted = g[horse_cols].shift(-i).fillna(g[horse_cols].iloc[i]).reset_index(drop=True) # 重命名列名,添加后缀 shifted.columns = [f"{col}_{suffix}" for col in horse_cols] # 合并到结果集 result = pd.concat([result, shifted], axis=1) return result # 执行处理并重置索引 new_df = df.groupby('raceId').apply(process_group).reset_index(drop=True) # 输出结果(转为字典格式匹配预期) print(new_df.to_dict('list'))
关键说明:
shift(-i)实现循环移位逻辑,结合fillna保证移位后末尾缺失的行用开头数据补充,形成循环效果- 分组处理确保不同场次的赛马数据不会互相干扰
- 用
concat直接合并列,比循环行操作的效率更高,避免原代码中merge和iterrows的性能问题
内容的提问来源于stack exchange,提问作者Jared King
相关产品推荐
相关产品推荐

