为什么groupby sum不将布尔值转换为整数或浮点数?

17

我将从三个简单的例子开始:

pd.DataFrame([[True]]).sum()

0    1
dtype: int64

pd.DataFrame([True]).sum()

0    1
dtype: int64

pd.Series([True]).sum()

1

这些都是预期的结果。这里有一个更复杂的示例。
df = pd.DataFrame([
        ['a', 'A', True],
        ['a', 'B', False],
        ['a', 'C', True],
        ['b', 'A', True],
        ['b', 'B', True],
        ['b', 'C', False],
    ], columns=list('XYZ'))

df.Z.sum()

4

同样符合预期。但是,如果我使用 groupby(['X', 'Y']).sum(),它会变成这个样子:

enter image description here

我以为结果应该是这个样子的:

enter image description here

我认为这是一个错误。还有其他的解释吗?


根据 @unutbu 的回答

pandas 试图重新编码为原始 dtype。我曾认为也许我执行的 group by 操作并没有真正分组任何内容。所以我尝试了这个示例,来测试这个想法。

df = pd.DataFrame([
        ['a', 'A', False],
        ['a', 'B', False],
        ['a', 'C', True],
        ['b', 'A', False],
        ['b', 'B', False],
        ['b', 'C', False],
    ], columns=list('XYZ'))

我将对'X'进行“分组”和“求和”。如果@unutbu正确,这些总和应为1和0,并且可转换为“bool”类型,因此我们应该看到“bool”。
df.groupby('X').sum()

在此输入图片描述

果然...bool

但如果过程相同,但值略有不同呢?

df = pd.DataFrame([
        ['a', 'A', True],
        ['a', 'B', False],
        ['a', 'C', True],
        ['b', 'A', False],
        ['b', 'B', False],
        ['b', 'C', False],
    ], columns=list('XYZ'))

df.groupby('X').sum()

在此输入图片描述

得出的教训是,做这件事时总是要使用astype(int)或类似的东西。

df.groupby('X').sum().astype(int)

无论是哪种场景,都可以获得一致的结果。


1
我也会称之为一个 bug,特别是在执行 df['Z'] = df['Z'].astype(int) 后得到了预期的结果。去报告一下,看看 pandas 的开发人员是否有这种行为的原因。 - Alicia Garcia-Raboso
2
这是因为_cython_agg_blocks调用了_try_coerce_and_cast_result,该函数又调用_try_cast_result,后者试图返回与原始值(在本例中为bool相同dtype的结果。 - unutbu
1
@unutbu 我能理解这个决定的优点。然而,这似乎意味着当使用分组聚合时,我们应该始终将其转换为我们期望的类型。问题是,你能把这个作为答案发表吗,这样它就会显示为已回答?谢谢! - piRSquared
1个回答

13
这是因为_cython_agg_blocks调用了_try_coerce_and_cast_result,它又调用了_try_cast_result,后者试图返回与原始值相同的数据类型(在本例中为bool)。
Z的数据类型为布尔型时,并且所有组中都没有超过一个True值时,会返回一些奇特的结果。如果任何一组有2个或更多True值,则由于_try_cast_result不会将2.0转换回布尔型,因此生成的值将为浮点数。
Z的数据类型为int时,_try_cast_result做得更有用:在df.groupby(['X', 'Y']).sum()使用的Cython聚合器内部,返回的result数据类型为float。 在这种情况下,_try_cast_result将结果返回到int数据类型。

那么,bug 修复了吗?我在使用 pandas 版本 1.2.4 时遇到了同样的问题。 - Miguel Gonzalez

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接