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

如何向量化Pandas DataFrame中两列组合的groupby操作

优化Pandas多列组合GroupBy的向量化方案

需求说明

现有一个Pandas DataFrame,需对列['A','B','C','D','E','F','G']的所有两列组合执行groupby操作,计算Feature_1和Feature_2的求和值。当前通过循环实现,但数据量较大时耗时较长,需更高效的向量化优化方法。

示例数据

import pandas as pd

d = {'A': [0,1,1,0,0,1,0,0],
     'B': [1,1,0,0,0,1,0,1],
     'C': [0,0,1,1,0,0,1,0],
     'D': [1,1,1,0,0,1,0,0],
     'E': [0,0,0,1,0,0,0,1],
     'F': [0,0,1,1,0,0,1,0],
     'G': [1,0,1,1,0,0,0,0],
     'Feature_1':[1,0,1,1,0,1,1,0],
     'Feature_2':[0,1,1,0,1,0,0,1]}

df = pd.DataFrame(d)
print(df)

输出:

A  B  C  D  E  F  G  Feature_1  Feature_2
0  0  1  0  1  0  0  1          1          0
1  1  1  0  1  0  0  0          0          1
2  1  0  1  1  0  1  1          1          1
3  0  0  1  0  1  1  1          1          0
4  0  0  0  0  0  0  0          0          1
5  1  1  0  1  0  0  0          1          0
6  0  0  1  0  0  1  0          1          0
7  0  1  0  0  1  0  0          0          1

期望输出

Col_1 Col_2  Col_1_value  Col_2_value  Feature_1_Sum  Feature_2_Sum
0     A     B            0            0              2              1
1     A     B            0            1              1              1
2     A     B            1            0              1              1
3     A     B            1            1              1              1
0     A     C            0            0              1              2
...  ...   ...          ...          ...            ...            ...
3     E     G            1            1              1              0
0     F     G            0            0              1              3
1     F     G            0            1              1              0
2     F     G            1            0              1              0
3     F     G            1            1              2              1

77 rows × 6 columns

当前循环实现代码

from itertools import combinations

cols_list = ['A','B','C','D','E','F','G']

i=0

for comb in combinations(cols_list, 2):
    i=i+1

    comb_list = [comb[0], comb[1]]

    try:
        del df_gp
    except Exception as e:
        pass

    try:
        del df_comb
    except Exception as e:
        pass

    df_gp = (df.groupby(by=comb_list).agg(Feature_1_Sum=('Feature_1','sum'), Feature_2_Sum=('Feature_2','sum')).reset_index())

    df_gp['Col_1'] = comb[0]
    df_gp['Col_2'] = comb[1]

    df_gp['Col_1_value'] = df_gp[comb[0]]
    df_gp['Col_2_value'] = df_gp[comb[1]]

    df_comb = pd.DataFrame()

    cols = ['Col_1','Col_2','Col_1_value','Col_2_value','Feature_1_Sum','Feature_2_Sum']
    df_comb = df_gp[cols]

    if i==1:
        df_agg = df_comb
    else:
        df_agg = pd.concat([df_agg, df_comb])

df_agg

优化方案

方法1:利用pd.crosstab高效计算分组求和 + 批量合并结果

原循环的主要开销在于多次创建中间DataFrame和反复执行pd.concat,我们可以通过pd.crosstab直接生成每个列对的2x2求和矩阵,再统一转换为目标格式,最后一次性合并所有结果,大幅提升效率。

import pandas as pd
from itertools import combinations

cols_list = ['A','B','C','D','E','F','G']
result_list = []

for col1, col2 in combinations(cols_list, 2):
    # 计算Feature_1的列对求和矩阵
    ct1 = pd.crosstab(df[col1], df[col2], values=df['Feature_1'], aggfunc='sum').fillna(0).astype(int)
    # 计算Feature_2的列对求和矩阵
    ct2 = pd.crosstab(df[col1], df[col2], values=df['Feature_2'], aggfunc='sum').fillna(0).astype(int)
    
    # 合并两个矩阵并转换为长格式
    merged = ct1.stack().reset_index(name='Feature_1_Sum')
    merged['Feature_2_Sum'] = ct2.stack().values
    
    # 重命名列并添加列标识
    merged.columns = ['Col_1_value', 'Col_2_value', 'Feature_1_Sum', 'Feature_2_Sum']
    merged['Col_1'] = col1
    merged['Col_2'] = col2
    
    # 调整列顺序为目标格式
    merged = merged[['Col_1', 'Col_2', 'Col_1_value', 'Col_2_value', 'Feature_1_Sum', 'Feature_2_Sum']]
    result_list.append(merged)

# 一次性合并所有结果
df_agg = pd.concat(result_list, ignore_index=True)
print(df_agg)

方法2:向量化生成所有组合统计量(进阶)

如果数据量极大,还可以利用numpy的广播机制直接计算所有列对的分组求和,彻底避免Python循环:

import pandas as pd
import numpy as np
from itertools import combinations

cols_list = ['A','B','C','D','E','F','G']
X = df[cols_list].values  # shape (n_rows, 7)
f1 = df['Feature_1'].values.reshape(-1,1)  # shape (n_rows,1)
f2 = df['Feature_2'].values.reshape(-1,1)

# 生成所有列对的索引组合
col_pairs = list(combinations(range(len(cols_list)), 2))
result_data = []

for i,j in col_pairs:
    # 获取当前列对的取值
    x1 = X[:,i]
    x2 = X[:,j]
    # 生成唯一分组键(0-3,对应0&0,0&1,1&0,1&1)
    groups = x1 * 2 + x2
    # 计算每个分组的特征和
    u, idx = np.unique(groups, return_inverse=True)
    f1_sum = np.bincount(idx, weights=f1.flatten(), minlength=4)
    f2_sum = np.bincount(idx, weights=f2.flatten(), minlength=4)
    
    # 转换为目标格式的行数据
    for g in range(4):
        val1 = g // 2
        val2 = g % 2
        result_data.append([cols_list[i], cols_list[j], val1, val2, int(f1_sum[g]), int(f2_sum[g])])

# 转换为DataFrame
df_agg = pd.DataFrame(result_data, columns=['Col_1', 'Col_2', 'Col_1_value', 'Col_2_value', 'Feature_1_Sum', 'Feature_2_Sum'])
print(df_agg)

这个方法利用numpy的底层数组运算,比纯Pandas操作更快,适合超大规模数据集。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.21 04:02:06