我将从3个简单的例子开始:
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()
我希望它看起来像:
我在想bug。还有其他解释吗?
Per @ unutbu的回答
pandas试图重铸为原始dtypes。我曾经想过,也许我所表演的那个小组并没有真正的团结。所以我尝试了这个例子来测试这个想法。df = pd.DataFrame([
['a', 'A', False],
['a', 'B', False],
['a', 'C', True],
['b', 'A', False],
['b', 'B', False],
['b', 'C', False],
], columns=list('XYZ'))
我groupby('X')
和sum
。如果@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)
为两种情况提供一致的结果。
答案 0 :(得分:7)
这是因为_cython_agg_blocks
调用_try_coerce_and_cast_result
调用_try_cast_result
,它会尝试返回与原始值相同的dtype 的结果(在这种情况下, bool
)。
当Z
具有dtype bool(并且所有组都具有不超过一个True值)时,这会返回一些有点奇怪的东西。如果任何组具有2个或更多True值,则结果值为浮点数,因为_try_cast_result
不会将2.0转换回布尔值。
_try_cast_result
具有dtype Z
时, int
会更有用:内部使用的Cython聚合器
df.groupby(['X', 'Y']).sum()
返回result
dtype float
。然后,_try_cast_result
将结果返回给dtype int
。