如何在Python pandas中对分组数据框应用函数?

3 投票
2 回答
1649 浏览
提问于 2025-04-17 16:56

我正在按照数据框中的一列对数据进行分组,下面是一个使用 iris 数据集的例子:

grouped_iris = iris.groupby(by="Name")

我想对每个组应用一个函数,这个函数会对 grouped_iris 中某些列进行特定的操作。具体来说,我想对每个组(每个 Name 的值)计算 PetalLengthPetalWidth 的总和,并把结果放在一个叫做 SumLengthWidth 的新列里。我知道我可以用 agg 来对每个组的所有列进行求和,像这样:

grouped_iris.agg(sum)

但我想要的是一个变体:我不想对每个 Name 的所有列求和,而是只对某些特定的列(SepalWidth, SepalLength)进行求和。谢谢。

2 个回答

2

这看起来有点不太优雅,但能完成任务:

grouped_iris[['PetalLength', 'PetalWidth']].sum().sum(axis=1)
2

不太清楚你是想要总的数字(如果是这样,Andy的解决方案就是你需要的),还是想把数据变回原来的数据框。如果是后者,你可以使用 transform

In [33]: cols = ['PetalLength', 'PetalWidth']

In [34]: transformed = grouped_iris[cols].transform(sum).sum(axis=1)

In [35]: iris['SumLengthWidth'] = transformed

In [36]: iris.head()
Out[36]: 
   SepalLength  SepalWidth  PetalLength  PetalWidth         Name  SumLengthWidth
0          5.1         3.5          1.4         0.2  Iris-setosa            85.4
1          4.9         3.0          1.4         0.2  Iris-setosa            85.4
2          4.7         3.2          1.3         0.2  Iris-setosa            85.4
3          4.6         3.1          1.5         0.2  Iris-setosa            85.4
4          5.0         3.6          1.4         0.2  Iris-setosa            85.4

编辑: 一般情况的例子

通常,对于一个数据框 df,使用 sum 来进行分组汇总会给你每个组的总和。

In [47]: df
Out[47]: 
  Name  val1  val2
0  foo     6     3
1  bar    17     4
2  foo    16     6
3  bar     7     3
4  foo     6    13
5  bar     7     1

In [48]: grouped = df.groupby('Name')

In [49]: grouped.agg(sum)
Out[49]: 
      val1  val2
Name            
bar     31     8
foo     28    22

在你的情况下,你想要对这些行进行求和:

In [50]: grouped.agg(sum).sum(axis=1)
Out[50]: 
Name
bar     39
foo     50

但这样只会给你两个数字;每个组一个。在一般情况下,如果你想把这两个数字映射回 原始 数据框,你需要使用 transform

In [51]: grouped.transform(sum)
Out[51]: 
   val1  val2
0    28    22
1    31     8
2    28    22
3    31     8
4    28    22
5    31     8

注意这些值和 agg 产生的值是完全一样的,但是它的维度和原始的 df 是一样的。还要注意,每个其他值都是重复的,因为行 [0, 2, 4] 和 [1, 3, 5] 是同一组。在你的情况下,你想要这两个值的总和,所以你需要对这些行进行求和。

In [52]: grouped.transform(sum).sum(axis=1)
Out[52]: 
0    50
1    39
2    50
3    39
4    50
5    39

现在你有一个和原始数据框长度相同的序列,所以你可以把它作为一列重新赋值(或者随便处理它):

In [53]: df['val1 + val2 by Name'] = grouped.transform(sum).sum(axis=1)

In [54]: df
Out[54]: 
  Name  val1  val2  val1 + val2 by Name
0  foo     6     3                   50
1  bar    17     4                   39
2  foo    16     6                   50
3  bar     7     3                   39
4  foo     6    13                   50
5  bar     7     1                   39

撰写回答