python - 当 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
这可能是什么原因造成的?
解决方案
让我们从一些简单的分组计算开始,以了解 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]
,并且意外地没有被聚合更改。
推荐阅读
- javascript - React Input 字段在被替换后不断恢复为默认文本
- c - 移动数组中的元素时设置方向的问题
- sql - 使数据库列不可编辑
- java - 如何为 Java 最终字符串查询正确翻译灵活的搜索查询?
- python - 当我们有多个子字符串时,如何使用 python 替换字符串的特定子字符串?
- c++ - 如何在 C++ 中将数字转换为链表
- android - 单击按钮时没有任何反应(Android Studio)
- python - 如何将非数字字符添加到numpy矩阵中的某个元素?
- swift - 有没有办法在同一个 XCODE 项目中重用代码?
- javascript - Codemirror Clike 模式似乎不起作用