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

如何将DataFrame的B类数组列转为无重复元素对的新行结构

问题描述

现有如下结构的DataFrame,其中Group是分组标识,A_x、A_y是A类物品的属性,B_m、B_n是B类物品的属性列表:

import pandas as pd

df = pd.DataFrame(
    data=[
        [0, 4, 9, [8, 7, 3], [-10, 5, 2]],
        [0, 1, 2, [8, 7, 3], [-10, 5, 2]],
        [1, 3, 3, [1, 2], [-5, 1]],
    ],
    columns=['Group', 'A_x', 'A_y', 'B_m', 'B_n'],
)

初始DataFrame输出:

Group  A_x  A_y        B_m          B_n
0      0    4    9  [8, 7, 3]  [-10, 5, 2]
1      0    1    2  [8, 7, 3]  [-10, 5, 2]
2      1    3    3     [1, 2]      [-5, 1]

需要将B_m和B_n列转换为每行仅含单个元素的四列(B_m1、B_n1、B_m2、B_n2),生成所有无重复的两两元素对,最终期望结果如下:

expected = pd.DataFrame(
    data=[
        [0, 4, 9, 8, -10, 7, 5],
        [0, 4, 9, 8, -10, 3, 2],
        [0, 4, 9, 7, 5, 3, 2],
        [0, 1, 2, 8, -10, 7, 5],
        [0, 1, 2, 8, -10, 3, 2],
        [0, 1, 2, 7, 5, 3, 2],
        [1, 3, 3, 1, -5, 2, 1],
    ],
    columns=['Group', 'A_x', 'A_y', 'B_m1', 'B_n1', 'B_m2', 'B_n2'],
)

期望结果输出:

Group  A_x  A_y  B_m1  B_n1  B_m2  B_n2
0      0    4    9     8   -10     7     5
1      0    4    9     8   -10     3     2
2      0    4    9     7     5     3     2
3      0    1    2     8   -10     7     5
4      0    1    2     8   -10     3     2
5      0    1    2     7     5     3     2
6      1    3    3     1    -5     2     1

已尝试用itertools.combinations结合循环实现,但希望得到更简洁的解决方案。

简洁解决方案

方法1:利用apply生成组合并展开

这种方法适合中小数据量,代码简洁直观:

from itertools import combinations
import pandas as pd

def generate_pairs(row):
    # 将B_m和B_n的元素一一配对
    b_items = list(zip(row['B_m'], row['B_n']))
    # 生成所有无重复的两两组合
    combos = list(combinations(b_items, 2))
    # 转换为目标格式的行数据
    return pd.DataFrame([
        [row['Group'], row['A_x'], row['A_y'], 
         combo[0][0], combo[0][1], combo[1][0], combo[1][1]]
        for combo in combos
    ], columns=['Group', 'A_x', 'A_y', 'B_m1', 'B_n1', 'B_m2', 'B_n2'])

# 对每行应用函数,合并所有结果
result = pd.concat(df.apply(generate_pairs, axis=1).tolist(), ignore_index=True)
print(result)

方法2:先展开B类属性,再生成组合(适合大数据量)

如果数据量较大,逐行循环效率较低,可以先展开B类属性,再按分组生成组合:

from itertools import combinations
import pandas as pd

# 先展开B_m和B_n列,将列表元素拆分为单独行
df_expanded = df.explode(['B_m', 'B_n']).reset_index(drop=True)
# 给每个分组内的B项添加索引,方便后续生成组合
df_expanded['b_idx'] = df_expanded.groupby(['Group', 'A_x', 'A_y']).cumcount()

# 生成每个分组内的两两索引组合
def get_combo_indices(group):
    indices = group['b_idx'].tolist()
    return pd.DataFrame(list(combinations(indices, 2)), columns=['idx1', 'idx2'])

combo_indices = df_expanded.groupby(['Group', 'A_x', 'A_y']).apply(get_combo_indices).reset_index()

# 两次合并,分别获取每组组合对应的B属性
result = combo_indices.merge(
    df_expanded, left_on=['Group', 'A_x', 'A_y', 'idx1'], right_on=['Group', 'A_x', 'A_y', 'b_idx']
).merge(
    df_expanded, left_on=['Group', 'A_x', 'A_y', 'idx2'], right_on=['Group', 'A_x', 'A_y', 'b_idx'], suffixes=('_1', '_2')
)

# 筛选并重命名列,得到最终结果
result = result[['Group', 'A_x', 'A_y', 'B_m_1', 'B_n_1', 'B_m_2', 'B_n_2']].rename(
    columns={'B_m_1':'B_m1', 'B_n_1':'B_n1', 'B_m_2':'B_m2', 'B_n_2':'B_n2'}
).reset_index(drop=True)

print(result)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.03 11:54:51