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

求助:如何在Pandas分组(groupby)内高效实现笛卡尔积

分组内高效生成笛卡尔积的优化方案

原循环+merge(cross)的方案性能瓶颈在于:每次循环拼接都会生成新DataFrame,内存开销大;且单个分组的merge(cross)未利用向量运算优势。以下是两种更高效的实现方式:

方案一:基于Numpy向量化生成索引对

利用Numpy的meshgrid快速生成分组内的行对索引,再批量从原表取数,避免多次拼接和merge的额外开销,适合大分组场景:

import pandas as pd
import numpy as np

# 给每个分组内的行添加序号
df['group_idx'] = df.groupby('owner').cumcount()

# 获取每个分组的行数
group_sizes = df.groupby('owner')['group_idx'].max() + 1

# 生成所有分组的笛卡尔积索引对
idx_pairs = []
for size in group_sizes:
    x, y = np.meshgrid(np.arange(size), np.arange(size))
    # 若不需要自身配对,可添加过滤条件:[x.ravel() != y.ravel()]
    idx_pairs.append(np.column_stack([x.ravel(), y.ravel()]))

# 生成重复的owner列表,对应每个索引对
owner_repeat = np.repeat(group_sizes.index, group_sizes ** 2)
# 合并所有索引对
all_idx = np.concatenate(idx_pairs)

# 按索引对提取左右表数据
left_df = df.set_index(['owner', 'group_idx']).loc[zip(owner_repeat, all_idx[:,0]), :].reset_index()
right_df = df.set_index(['owner', 'group_idx']).loc[zip(owner_repeat, all_idx[:,1]), :].reset_index()

# 重命名右表列名避免冲突
right_df = right_df.rename(columns={col: f"{col}_right" for col in right_df.columns if col != 'owner'})

# 合并结果
result = pd.merge(left_df, right_df, on='owner').drop(['group_idx', 'group_idx_right'], axis=1)

方案二:Groupby结合MultiIndex生成笛卡尔积

利用Pandas的MultiIndex.from_product直接生成分组内的行对索引,适合分组数量多但单个分组较小的场景:

import pandas as pd

def cross_group(group):
    n_rows = len(group)
    # 生成分组内所有行对的索引
    pair_idx = pd.MultiIndex.from_product([group.index, group.index], names=['left_idx', 'right_idx'])
    # 若不需要自身配对,添加过滤:pair_idx = pair_idx[pair_idx.get_level_values(0) != pair_idx.get_level_values(1)]
    
    # 提取左右表数据并拼接
    left = group.loc[pair_idx.get_level_values(0)].reset_index(drop=True)
    right = group.loc[pair_idx.get_level_values(1)].reset_index(drop=True).rename(columns=lambda x: f"{x}_right")
    return pd.concat([left, right], axis=1)

# 分组处理并合并结果
result = df.groupby('owner', group_keys=False).apply(cross_group).reset_index(drop=True)

性能优化提示

  • 如果不需要行与自身的配对,在生成索引对时添加过滤条件,可大幅减少最终数据量和计算时间;
  • 若数据集远超内存,可考虑分块处理分组,避免一次性加载所有数据。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.30 20:24:31