繁体   English   中英

为什么 groupby 操作的行为不同

[英]Why does groupby operations behave differently

当使用pandas groupby 函数并在 groupby 之后操作 output 时,我注意到某些函数在作为索引返回的内容以及如何操作方面表现不同。

假设我们有一个 dataframe,其中包含以下信息:

    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()  

我们得到一个DataFrame

             ID
Name  Type     
Book1 ebook   2
Book2 paper   4
Book3 paper   3

其中包含一个 MultiIndex,其中包含 groupby 中使用的列:

MultiIndex([('Book1', 'ebook'),
            ('Book2', 'paper'),
            ('Book3', 'paper')],
           names=['Name', 'Type'])

和一列称为ID

但如果我应用size() function,结果是一个Series

Name   Type 
Book1  ebook    2
Book2  paper    2
Book3  paper    1
dtype: int64

最后,如果我执行pct_change() ,我们只会得到结果 DataFrame 列:

    ID
0   NaN
1   NaN
2   NaN
3   0.0
4   0.0

长话短说;博士。 我想知道为什么有些函数返回一个Series而有些函数返回一个DataFrame ,因为这让我在处理同一个 DataFrame 中的不同操作时感到困惑。

从文件

尺码:

 Returns Series Number of rows in each group.

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

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

Function 像diffpct_change不是 agg,它会返回与原始 dataframe 相同index的值,对于countmeansum它们是 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 object 的聚合也是如此groupby所做的所有第一部分都是创建从 DataFrame 到组的映射。 因为这并没有真正做任何事情,所以没有理由为什么具有不同操作的相同 groupby 需要返回相同类型的 output(见上文)。

gp = df.groupby(["Name", "Type"])
# Haven't done any aggregations yet...

这里的另一个重要部分是我们有一个DataFrame GroupBy object。还有Series GroupBy 对象,这种差异可以改变返回值。

gp
#<pandas.core.groupby.generic.DataFrameGroupBy object>

那么聚合时会发生什么?

使用DataFrameGroupBy ,当您选择聚合(如sum )时,每组折叠为单个值,返回值将是 DataFrame,其中索引是唯一的分组键。 返回值是DataFrame ,因为我们提供了一个 DataFrameGroupBy object。DataFrame 可以有多个列,如果有另一个数字列,它也会聚合该列,因此需要 DataFrame output。

gp.sum()
#             ID
#Name  Type     
#Book1 ebook   2
#Book2 paper   4
#Book3 paper   3

另一方面,如果您使用 SeriesGroupBy object(使用[]选择单个列),那么您将返回一个系列,同样带有唯一组键的索引。

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

#Name   Type 
#Book1  ebook    2
#Book2  paper    4
#Book3  paper    3
#Name: ID, dtype: int64

对于返回 arrays 的聚合(如cumsumpct_change ),DataFrameGroupBy 将返回 DataFrame,而 SeriesGroupBy 将返回一个系列。 但是索引不再是唯一的组键。 这是因为那没有什么意义; 通常,您希望在组内进行计算,然后将结果分配回原始 DataFrame。因此,返回的索引与您为聚合提供的原始 DataFrame 一样。 这使得创建这些列非常简单,因为 pandas 处理所有 alignment

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

但是size呢? 那个有点奇怪 组的size是一个标量。 该组有多少列或这些列中的值是否丢失并不重要,因此向其发送 DataFrameGroupBy 或 SeriesGroupBy object 是无关紧要的。 结果pandas将始终返回一个Series 再次作为一个返回标量的组级聚合,让返回值由唯一的组键索引是有意义的。

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

最后为了完整起见,尽管像sum这样的聚合返回单个标量值,但将这些值带回原始 DataFrame 中该组的每一行通常很有用。但是,正常.sum的返回具有不同的索引,因此它不会对齐。 您可以将值merge回唯一键,但pandas提供了transform这些聚合的能力。 由于此处的目的是将其恢复为原始 DataFrame,因此 Series/DataFrame 的索引与原始输入相同

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM