Pandas按特定列分组并求和

1 投票
2 回答
3130 浏览
提问于 2025-04-18 07:17

下面是一个简单的例子,展示了我遇到的问题。我们初始的状态如下(我只是用字典来演示):

A = [{'D': '16.5.2013', 'A':1, 'B': 0.0, 'C': 2}, {'D': '16.5.2013', 'A':1, 'B': 0.0, 'C': 4}, {'D': '16.5.2013', 'A':1, 'B': 0.5, 'C': 7}]
df = pd.DataFrame(A)
>>> df
   A    B  C          D
0  1  0.0  2  16.5.2013
1  1  0.0  4  16.5.2013
2  1  0.5  7  16.5.2013

我想知道如何从 df 转换到 df_new,结果是:

A_new = [{'D': '16.5.2013', 'A':1, 'B': 0.0, 'C': 6}, {'D': '16.5.2013', 'A':1, 'B': 0.5, 'C': 7}]
df_new = pd.DataFrame(A_new)

>>> df_new
   A    B  C          D
0  1  0.0  6  16.5.2013
1  1  0.5  7  16.5.2013

因为 'B' 列的值在前两行是相同的,所以 'C' 列的前两行会被加在一起。其他的列保持不变,比如 'A' 列不进行求和,'D' 列也不变。我该怎么做,假设我只有 df,想要得到 df_new。如果能找到一种优雅的解决方案,我会非常感激。

提前谢谢大家。

2 个回答

2

假设其他列的数据总是相同的,不需要特别处理。

首先,创建一个新的数据框 df_new,按照 B 列进行分组,在每个组中取每一列的第一行数据:

In [17]: df_new = df.groupby('B', as_index=False).first()

然后,专门对 C 列进行计算,求出每个组的总和:

In [18]: df_new['C'] = df.groupby('B', as_index=False)['C'].sum()['C']

In [19]: df_new
Out[19]: 
     B  A  C          D
0  0.0  1  6  16.5.2013
1  0.5  1  7  16.5.2013

如果你的列数不多,也可以一步到位(不过如果列数多的话,上面的方式会更方便,不用手动处理太多),可以为每一列指定想要的计算方法:

In [20]: df_new = df.groupby('B', as_index=False).agg({'A':'first', 'C':'sum', 'D':'first'})
0

如果A和D在按B分组时总是相等,那么你可以只按A、B和D分组,然后对C进行求和:

df.groupby(['A', 'B', 'D'], as_index = False).agg(sum)

输出结果:

   A    B          D  C
0  1  0.0  16.5.2013  6
1  1  0.5  16.5.2013  7

另外:

你其实是想要把数据按B这一列进行汇总。要对C这一列进行汇总,你只需要使用内置的sum函数。对于其他列,你基本上只想选择一个值,因为你认为它们在每个组内总是相同。为此,只需写一个非常简单的函数,通过取第一个值来汇总这些列。

# will take first value of the grouped data
sole_value = lambda x : list(x)[0]

#dictionary that maps columns to aggregation functions
agg_funcs = {'A' : sole_value, 'C' : sum, 'D' : sole_value}

#group and aggregate
df.groupby('B', as_index = False).agg(agg_funcs)

输出结果:

     B  A  C          D
0  0.0  1  6  16.5.2013
1  0.5  1  7  16.5.2013

当然,你需要确保A和D这两列的值确实是相等的,否则你可能会保留错误的数据。

撰写回答