首页 > 解决方案 > 当 NaN 在组列中时,Pandas groupby 会应用奇怪的行为

问题描述

我遇到了一些意想不到的 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 开头的 group 列有关,但后来我尝试删除最后一行,我再次得到了预期的结果,所以显然原因是别的。

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

这可能是什么原因造成的?

标签: pythonpandasnumpydataframepandas-groupby

解决方案


让我们从一些简单的分组计算开始,以了解 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. 对于 group key 0.0,原始块的索引是[0, 2, 3],而它是[1, 2, 3]聚合之后的。但是,对于df2,原始索引是[1, 2, 3],并且意外地没有被聚合更改。


推荐阅读