Python 为什么groupby操作表现不同
在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() 我们得到一个数据帧:
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