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

如何用Pandas GroupBy实现DataFrame的复杂双重求和计算

在Pandas中按分组实现带双哑变量的复杂求和

问题背景

给定如下结构的Pandas DataFrame:

import pandas as pd

df = pd.DataFrame({
    'Race_ID': [1,1,1,1,2,2,2],
    'Date': ['1/1/2023','1/1/2023','1/1/2023','1/1/2023','11/9/2022','11/9/2022','11/9/2022'],
    'Student_ID': [1,2,3,4,1,2,3],
    'a': [3,2,1,4,2,3,1],
    'b': [1,2,4,1,6,2,6]
})

需要按Race_ID分组,为每行新增sum列,其值由以下双重求和公式计算:
$$\sum_{1\leq k \leq n_{RaceID} \atop{k\not=i}}\sum_{1\leq j \leq n_{RaceID} \atop{j \notin {i, k}}}a_kb_j$$
其中:

  • $i$为当前行在分组内的索引
  • $n_{RaceID}$为对应分组的行数
  • 实际场景中求和项并非可分离的a_kb_j形式,因此无法通过数学拆分简化计算

解决方案

方法1:分组遍历实现(直观通用)

通过groupby.apply对每个分组单独处理,遍历每行$i$,再遍历符合条件的$k$和$j$计算求和:

def calculate_group_sum(group):
    n = len(group)
    a_vals = group['a'].values
    b_vals = group['b'].values
    sum_results = []
    
    for i in range(n):
        total = 0
        # 遍历所有k≠i
        for k in range(n):
            if k == i:
                continue
            # 遍历所有j∉{i,k}
            for j in range(n):
                if j == i or j == k:
                    continue
                # 替换此处为实际的自定义函数,示例为a_k*b_j
                total += a_vals[k] * b_vals[j]
        sum_results.append(total)
    
    group['sum'] = sum_results
    return group

# 应用到分组数据
result_df = df.groupby('Race_ID', group_keys=False).apply(calculate_group_sum)

方法2:向量化优化(适合大数据量)

利用Numpy生成掩码矩阵,减少循环次数,提升效率:

import numpy as np

def calculate_group_sum_vectorized(group):
    n = len(group)
    a = group['a'].values.reshape(-1, 1)
    b = group['b'].values.reshape(1, -1)
    
    # 生成求和项矩阵,替换此处为实际自定义函数的矩阵计算
    # 示例为a_k*b_j的矩阵
    term_matrix = a @ b
    
    sum_results = []
    for i in range(n):
        # 生成掩码:排除j=i、k=i、j=k的情况
        mask = np.ones((n, n), dtype=bool)
        mask[i, :] = False  # 排除j=i
        mask[:, i] = False  # 排除k=i
        np.fill_diagonal(mask, False)  # 排除j=k
        
        # 对符合条件的项求和
        total = term_matrix[mask].sum()
        sum_results.append(total)
    
    group['sum'] = sum_results
    return group

# 应用到分组数据
result_df = df.groupby('Race_ID', group_keys=False).apply(calculate_group_sum_vectorized)

验证结果

运行上述代码后,result_df将生成符合预期的输出:

Race_ID        Date  Student_ID  a  b  sum
0        1    1/1/2023           1  3  1   37
1        1    1/1/2023           2  2  2   37
2        1    1/1/2023           3  1  4   25
3        1    1/1/2023           4  4  1   31
4        2  11/9/2022           1  2  6   20
5        2  11/9/2022           2  3  2   18
6        2  11/9/2022           3  1  6   22

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.27 13:20:48