如何用Pandas基于DataFrame组内序列关系生成配对DataFrame?
Pandas:按组匹配连续序列的元素对
问题背景
我们有如下原始数据(已导入为Pandas DataFrame old_df):
| elementID | groupID | sequence |
|---|---|---|
| abc | A | 0 |
| dcv | A | 1 |
| asd | B | 1 |
| ccc | B | 0 |
| abc | B | 2 |
需要生成一个新的DataFrame,每行记录同一groupID内序列连续的两个elementID,目标输出如下:
| elementID_1 | elementID_2 | groupID |
|---|---|---|
| abc | dcv | A |
| asd | abc | B |
| ccc | asd | B |
提问者最初尝试多行选择未成功,目前分步构建了部分new_df:
new_df = pd.DataFrame() new_df[['elementID_2', 'sequence', 'groupID']] = old_df.loc[old_df.sequence > 0][['elementID', 'sequence', 'groupID']]
现在需要匹配old_df中与new_df同groupID且sequence为new_df.sequence - 1的行,生成elementID_1列。
解决方案
这里推荐两种高效的实现方式:
方法1:使用merge关联匹配
我们可以基于groupID和计算后的sequence-1,将new_df与old_df进行关联,直接获取对应的elementID_1:
# 修正原代码的语法错误(old_df.loc.sequence改为old_df['sequence']) new_df = pd.DataFrame() new_df[['elementID_2', 'sequence', 'groupID']] = old_df.loc[old_df['sequence'] > 0][['elementID', 'sequence', 'groupID']] # 计算需要匹配的前序sequence new_df['prev_sequence'] = new_df['sequence'] - 1 # 关联old_df,获取对应的elementID作为elementID_1 new_df = new_df.merge( old_df[['elementID', 'groupID', 'sequence']], left_on=['groupID', 'prev_sequence'], right_on=['groupID', 'sequence'], how='left' ).rename(columns={'elementID': 'elementID_1'}) # 整理最终需要的列,并清理临时列 new_df = new_df[['elementID_1', 'elementID_2', 'groupID']]
方法2:按组排序后使用shift(更简洁)
既然我们需要的是同组内连续序列的元素对,其实可以先按groupID分组,对sequence排序后,用shift()获取前一个元素,再筛选出有效的连续对:
# 先按组和序列排序,确保顺序正确 old_df_sorted = old_df.sort_values(by=['groupID', 'sequence']).reset_index(drop=True) # 按组shift,获取前一个元素作为elementID_1 old_df_sorted['elementID_1'] = old_df_sorted.groupby('groupID')['elementID'].shift(1) # 重命名当前元素为elementID_2,并筛选出有前序元素的行(排除每组第一个元素) new_df = old_df_sorted.dropna(subset=['elementID_1']).rename(columns={'elementID': 'elementID_2'}) # 整理最终列顺序 new_df = new_df[['elementID_1', 'elementID_2', 'groupID']]
这两种方法都能得到你想要的目标输出,其中方法2更简洁高效,尤其适合数据量较大的场景。
内容的提问来源于stack exchange,提问作者roschach
相关产品推荐
相关产品推荐

