
本文介绍使用pandas按组生成列内元素所有无序二元组合(itertools.combinations(..., r=2))并拆分为新列的高效方法,适用于需对分组数据进行两两配对分析的场景。
本文介绍使用pandas按组生成列内元素所有无序二元组合(`itertools.combinations(..., r=2)`)并拆分为新列的高效方法,适用于需对分组数据进行两两配对分析的场景。
在数据分析中,常需将同一分组下的某列多个值两两配对(不重复、无序),并将每对值分别存入两个新列(如 B_m1/B_m2、B_n1/B_n2),同时保留原始分组键和其他关联字段。直接循环或手动构造极易出错且性能低下;而利用 pandas 的 groupby.apply 结合 itertools.combinations 可实现向量化、可读性强且高效的解决方案。
核心思路是:
- 将非目标列(如 'Group', 'A_x', 'A_y')作为分组依据;
- 对每个目标列(如 'B_m', 'B_n')在各组内独立生成所有长度为 2 的组合;
- 将每组组合结果转为 DataFrame,并重命名列为 {原列名}1 和 {原列名}2;
- 沿列方向(axis=1)拼接各目标列的结果,并恢复分组索引。
以下是完整可运行代码:
import pandas as pd
from itertools import combinations
df = pd.DataFrame(
data=[
[0, 4, 7, -1, 0.9],
[0, 4, 7, 0, 0.3],
[0, 4, 7, 1, 0.2],
[1, 3, 3, 1, 0.5],
[1, 3, 3, 0, 0.2],
[2, 1, 8, 0, 0.6],
],
columns=['Group', 'A_x', 'A_y', 'B_m', 'B_n'],
)
# 定义要展开的目标列与分组列
cols = ['B_m', 'B_n']
group_cols = list(df.columns.difference(cols, sort=False)) # ['Group', 'A_x', 'A_y']
# 分组后对每列应用组合生成 + 列重命名
g = df.groupby(group_cols, sort=False)
out = pd.concat([
g[c].apply(lambda x: pd.DataFrame(list(combinations(x, r=2))))
.rename(columns=lambda idx: f'{c}{idx+1}')
for c in cols
], axis=1).reset_index(group_cols)
print(out)
输出结果与预期一致:
Group A_x A_y B_m1 B_m2 B_n1 B_n2 0 0 4 7 -1.0 0.0 0.9 0.3 1 0 4 7 -1.0 1.0 0.9 0.2 2 0 4 7 0.0 1.0 0.3 0.2 3 1 3 3 1.0 0.0 0.5 0.2
✅ 注意事项:
- 自动过滤掉组内元素少于 2 个的组(因 combinations(..., r=2) 在长度
- 组合顺序遵循原始行序(即 (x_i, x_j) 中 i
- 若原始列含非数值类型(如字符串、类别),该方法同样适用;
- 对于大数据集,apply + list(combinations(...)) 仍属内存友好方案——避免了显式双重循环和中间列表累积。
该方法兼具简洁性与扩展性:只需修改 cols 列表即可批量处理多列,是 Pandas 分组组合展开任务的标准实践。











