我遇到了一些意想不到的Pandas groupby-apply结果,我想不出具体原因。
下面我得数据框除了2个值的排序之外都是相等的,df1产生的结果和我预期的一样,但是df2产生的结果完全不同。
import numpy as np
df1 = pd.DataFrame({'group_col': [0.0, np.nan, 0.0, 0.0], 'value_col': [2,2,2,2]})
df2 = pd.DataFrame({'group_col': [np.nan, 0.0, 0.0, 0.0], 'value_col': [2,2,2,2]})
df1:
group_col value_col
0 0.0 2
1 NaN 2
2 0.0 2
3 0.0 2
df2:
group_col value_col
0 NaN 2
1 0.0 2
2 0.0 2
3 0.0 2
当我把 group_col
并做一个value_counts的 value_col
每一个组,包括重新索引以包括所有可能的值,我得到以下df1的结果。
df1.groupby('group_col').value_col.apply(lambda x: x.value_counts().reindex(index=[1,2,3]))
group_col
0.0 1 NaN
2 3.0
3 NaN
Name: value_col, dtype: float64
它正确地找到了1个组,并返回了一个多索引系列,包含了每个可能值的value_counts。但是当我在df2上运行同样的程序时,得到的结果完全不同。
0 NaN
1 NaN
2 3.0
3 NaN
Name: value_col, dtype: float64
这里的结果包含一个与原始DataFrame匹配的索引,而不是我期望的多索引。我想这可能与以 np.nan 开头的组列有关,但后来我试着删除最后一行,我又得到了预期的结果,所以显然是其他原因造成的。
df2.head(3).groupby('group_col').value_col.apply(lambda x: x.value_counts().reindex(index=[1,2,3]))
group_col
0.0 1 NaN
2 2.0
3 NaN
Name: value_col, dtype: float64
可能是什么原因造成的呢?
我们先看一些简单的分组计算,了解pandas是如何在上面工作的。
在下面的案例中,分组键被用作结果中的索引。Series
对象。原来的索引被丢弃。
In [4]: df1.groupby('group_col')['value_col'] \
...: .apply(lambda x: {'sum': x.sum(), 'mean': x.mean()})
Out[4]:
group_col
0.0 sum 6.0
mean 2.0
Name: value_col, dtype: float64
In [5]: df2.groupby('group_col')['value_col'] \
...: .apply(lambda x: {'sum': x.sum(), 'mean': x.mean()})
Out[5]:
group_col
0.0 sum 6.0
mean 2.0
Name: value_col, dtype: float64
在接下来的情况下,原始的 DataFrame
被保存下来。分组键不包含在结果的 Series
.
In [6]: df1.groupby('group_col')['value_col'].apply(lambda x: x / len(x))
Out[6]:
0 0.666667
1 NaN
2 0.666667
3 0.666667
Name: value_col, dtype: float64
In [7]: df2.groupby('group_col')['value_col'].apply(lambda x: x / len(x))
Out[7]:
0 NaN
1 0.666667
2 0.666667
3 0.666667
Name: value_col, dtype: float64
是什么原因让pandas在产生组合对象的索引时表现不同呢?
其实,这是基于 指数是否被聚合变异了?. 当原始对象和结果对象之间的索引相同时,它选择重用原始索引。另一方面,当索引与原始对象之间的索引不同时,它使用索引中的组键形成一个 MultiIndex
.
现在,回到问题上,请注意,索引被改变了,因为它是为 df1
. 对于组键 0.0
,原始块的索引是 [0, 2, 3]
而它是 [1, 2, 3]
聚合后。然而,对于 df2
,原来的指数是 [1, 2, 3]
,意外的是,它并没有被聚集改变。