为什么Pandas中的"None | True"返回False,而Python中的"None or True"返回True?

25

在纯Python中,None or True返回True


但是,当我在pandas中对包含None值的两个Series执行|操作时,结果并不如我所期望:

>>> df.to_dict()
{'buybox': {0: None}, 'buybox_y': {0: True}}
>>> df
    buybox  buybox_y
0   None    True

>>> df['buybox'] = (df['buybox'] | df['buybox_y'])
>>> df
    buybox  buybox_y
0   False   True

期望结果:

>>> df
    buybox  buybox_y
0   True    True

我通过两次应用OR操作得到了想要的结果,但我不知道为什么要这样做。

我不是在寻找解决方法(我已经通过连续两次应用df['buybox'] = (df['buybox'] | df['buybox_y']) 得到了),而是在寻找解释,因此标题中有'why'。


11
|or 是两个完全不同的操作符。请注意,None | True 会产生类型错误。 - chepner
5
是的,但是 Pandas 使用 | 表示逻辑或,而我们并没有收到 TypeError 的错误信息。不知何故,我们得到了 False。 - user2357112
3
Pandas文档(https://pandas.pydata.org/pandas-docs/stable/user_guide/indexing.html#boolean-indexing)指出,符号“|”用于逻辑或,而不是位运算或。 我的pandas版本为1.2.0。 - politinsa
3
@CharlesDuffy 我不认为这个问题是那种为什么的问题。这里的为什么更多的是“这段代码做了与我期望的不同的事情。我漏掉了什么?哪里出了错?”这对我来说似乎是Stack Overflow上非常普遍且有意义的一类问题。指向pandas中或运算符的定义,或者解释这种行为是由哪个bug引起的(我不知道是哪种情况),可以回答这个问题。原帖并没有问为什么运算符被定义成那样,或者为什么会有一个bug;只有在那些情况下才会是你所提到的类型的问题。 - Jesper
3
@ Jesper,我基本上同意;问题在于OP忽略/将声称存在一个错误的评论视为不响应(并且问题添加了赏金,附带一条信息重新聚焦于感兴趣的是解释而不是解决方法),这导致了上述评论。 - Charles Duffy
显示剩余13条评论
2个回答

20

Pandas | 运算符不依赖于 Python 的 or 表达式,并且行为不同。

如果两个操作数都是布尔值,则结果在数学上被定义,并且对于 Python 和 Pandas 是相同的。

但在您的情况下,系列 "buybox" 的类型为 object,而 "buybox_y" 的类型为 bool。在这种情况下,Pandas | 运算符是不可交换的

  • 右操作数被强制转换为布尔值
  • 然后尝试执行按位或
    • None | True 是无效的操作,导致 None
  • 最终结果被强制转换为布尔值

因此,

>>> df['buybox'] | df['buybox_y']
0  False

>>> df['buybox_y'] | df['buybox']
0  True

为了获得可预测的结果,在进行布尔运算之前,您可以使用Pandas astype清理数据,并将其转换为布尔类型。


-1
对于布尔对象(即Py_True和Py_False),代码将进入快速处理分支;对于其他对象,将使用PyObject_IsTrue()计算int类型的值。
在计算过程中,PyObject_IsTrue()函数将依次获取nb_bool、mp_length和sq_length的值,这些值应该对应于两个魔术方法bool()和len()的返回值。

这可能是关于CPython中or运算符如何工作的真实且有趣的信息,但是这个问题完全不同,因为它涉及到两个pandas Series之间的|运算符的工作方式,这是一种完全不同的实现,既不匹配纯Python的or也不匹配| - Tim

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