Python 为什么groupby操作表现不同

Python 为什么groupby操作表现不同,python,pandas,dataframe,group-by,Python,Pandas,Dataframe,Group By,在groupby之后使用和操作输出时,我注意到一些函数在返回什么作为索引以及如何操作索引方面表现不同 假设我们有一个包含以下信息的数据帧: Name Type ID 0 Book1 ebook 1 1 Book2 paper 2 2 Book3 paper 3 3 Book1 ebook 1 4 Book2 paper 2 如果我们这样做 df.groupby([“Name”,“Type”]).sum() 我们得到一个数据帧:

在groupby之后使用和操作输出时,我注意到一些函数在返回什么作为索引以及如何操作索引方面表现不同

假设我们有一个包含以下信息的数据帧:

    Name   Type  ID
0  Book1  ebook   1
1  Book2  paper   2
2  Book3  paper   3
3  Book1  ebook   1
4  Book2  paper   2
如果我们这样做

df.groupby([“Name”,“Type”]).sum()
我们得到一个
数据帧

             ID
Name  Type     
Book1 ebook   2
Book2 paper   4
Book3 paper   3
其中包含一个包含groupby中使用的列的多索引:

MultiIndex([('Book1','ebook'),
(‘书2’、‘纸’),
(“书3”,“纸”),
名称=[“名称”,“类型”])
还有一列名为
ID

但是如果我应用
size()
函数,结果将是一个
系列

名称类型
第1册电子书2
第2册第2页
第3册论文1
数据类型:int64
最后,如果我做一个
pct\u change()
,我们只会得到结果DataFrame列:

ID
0南
1楠
2楠
3   0.0
4   0.0
TL;DR.我想知道为什么有些函数返回一个
系列
,而有些函数返回一个
数据帧
,因为这让我在处理同一数据帧中的不同操作时感到困惑。

来自文档

:


对于
sum
,由于没有传递sum的列,因此它将返回不带groupby键的数据帧

df.groupby(["Name", "Type"])['ID'].sum()  # return Series


diff
pct\u change
这样的函数不是agg,它将返回与原始数据帧具有相同
索引的值,对于
count
mean
sum
它们是agg,返回值和
groupby
键作为索引

输出不同,因为聚合不同,而这些聚合主要控制返回的内容。请考虑等效的数组。数据相同,但一个“聚合”返回单个标量值,另一个返回与输入大小相同的数组

import numpy as np
np.array([1,2,3]).sum()
#6

np.array([1,2,3]).cumsum()
#array([1, 3, 6], dtype=int32)
DataFrameGroupBy对象的聚合也是如此。
groupby
的第一部分就是创建从数据帧到组的映射。由于这实际上没有任何作用,因此没有理由让具有不同操作的同一groupby返回相同类型的输出(见上文)

另一个重要的部分是我们有一个数据帧GroupBy对象。还有系列GroupBy对象,这种差异可能会改变回报

gp
#<pandas.core.groupby.generic.DataFrameGroupBy object>
另一方面,如果使用SeriesGroupBy对象(使用
[]
选择单个列),则将返回一个序列,同样使用唯一组键的索引

df.groupby(["Name", "Type"])['ID'].sum()
|------- SeriesGroupBy ----------|

#Name   Type 
#Book1  ebook    2
#Book2  paper    4
#Book3  paper    3
#Name: ID, dtype: int64
对于返回数组的聚合(如
cumsum
pct\u change
),DataFrameGroupBy将返回数据帧,SeriesGroupBy将返回序列。但是索引不再是唯一的组键。这是因为这毫无意义;通常,您希望在组内进行计算,然后将结果分配回原始数据帧。因此,返回的索引与您为聚合提供的原始数据帧类似。这使得创建这些列非常简单,因为熊猫可以处理所有对齐

df['ID_pct_change'] = gp.pct_change()

#    Name   Type  ID  ID_pct_change
#0  Book1  ebook   1            NaN  
#1  Book2  paper   2            NaN   
#2  Book3  paper   3            NaN   
#3  Book1  ebook   1            0.0  # Calculated from row 0 and aligned.
#4  Book2  paper   2            0.0

但是尺寸呢?那个有点奇怪。组的
大小
是一个标量。不管组有多少列,也不管这些列中的值是否丢失,因此向其发送DataFrameGroupBy或SeriesGroupBy对象是无关的。因此,
pandas
将始终返回一个
系列
。同样,作为一个返回标量的组级聚合,有必要使用唯一的组键对返回进行索引

gp.size()
#Name   Type 
#Book1  ebook    2
#Book2  paper    2
#Book3  paper    1
#dtype: int64

最后,为了完整性,尽管像
sum
这样的聚合返回单个标量值,但将这些值带回原始数据帧中该组的每一行通常是有用的。但是,正常
.sum
的返回具有不同的索引,因此它不会对齐。您可以
merge
将值重新合并到唯一键上,但是
pandas
提供了
转换这些聚合的能力。由于此处的目的是将其恢复到原始数据帧,因此序列/数据帧与原始输入一样被索引

gp.transform('sum')
#   ID
#0   2    # Row 0 is Book1 ebook which has a group sum of 2
#1   4
#2   3
#3   2    # Row 3 is also Book1 ebook which has a group sum of 2
#4   4

我明白了,但是缺乏标准有什么原因吗?如果操作返回了相同的结构,是否更容易?@ GabrielZiegler依赖于函数,例如,DIFF将返回每一行,但和将考虑整个GROUPBY值作为一个输出。非常感谢您这样一个专用的和说教的响应。
df['ID_pct_change'] = gp.pct_change()

#    Name   Type  ID  ID_pct_change
#0  Book1  ebook   1            NaN  
#1  Book2  paper   2            NaN   
#2  Book3  paper   3            NaN   
#3  Book1  ebook   1            0.0  # Calculated from row 0 and aligned.
#4  Book2  paper   2            0.0
gp.size()
#Name   Type 
#Book1  ebook    2
#Book2  paper    2
#Book3  paper    1
#dtype: int64
gp.transform('sum')
#   ID
#0   2    # Row 0 is Book1 ebook which has a group sum of 2
#1   4
#2   3
#3   2    # Row 3 is also Book1 ebook which has a group sum of 2
#4   4