【问题标题】:How does the Pandas deal with the situation when a column with type "object" is compared with an integer?当将“对象”类型的列与整数进行比较时,Pandas 如何处理这种情况?
【发布时间】:2019-01-25 06:56:04
【问题描述】:

我的问题是关于 pandas 用于将类型为“object”的列与整数进行比较的规则。这是我的代码:

In [334]: df
Out[334]: 
     c1    c2        c3  c4
id1   1    li -0.367860   5
id2   2  zhao -0.596926   5
id3   3   sun  0.493806   5
id4   4  wang -0.311407   5
id5   5  wang  0.253646   5

In [335]: df < 2
Out[335]: 
        c1    c2    c3     c4
id1   True  True  True  False
id2  False  True  True  False
id3  False  True  True  False
id4  False  True  True  False
id5  False  True  True  False

In [336]: df.dtypes
Out[336]: 
c1      int64
c2     object
c3    float64
c4      int64
dtype: object

为什么“c2”列的所有人都得到True

附:我也试过了:

In [333]: np.less(np.array(["s","b"]),2)
Out[333]: NotImplemented

【问题讨论】:

  • 有趣的是,df &gt; 2df &lt; 2 都产生了 True
  • 我尝试覆盖类的 le(小于)和 ge(大于)例程以始终返回 False,并且 df > 2仍然返回 True。我的猜测是,出于某种原因,pandas 会覆盖每个对象以在比较时返回 True。

标签: python pandas dataframe comparison-operators


【解决方案1】:

对于 DataFrame,与标量比较总是返回一个包含所有布尔列的 DataFrame。

我认为它没有正式记录在任何地方,但源代码中有一条注释(见下文)确认了预期的行为:

[用于] [在 DataFrame 和标量之间] 的直接布尔比较,我们希望允许所有列(无论 dtype 传递)参见 #4537 进行讨论。

实际上,这意味着每列的所有比较都必须返回TrueFalse。任何无效的比较(例如'li' &lt; 2)都应默认为这些布尔值之一。

简单地说,pandas 开发人员决定它应该默认为True

#4537 中对此行为进行了一些讨论,并提出了一些使用 False 的论据,或者将比较限制为仅具有兼容类型的列,但票证已关闭且未更改任何代码。

如果您有兴趣,可以在ops.py 中找到的内部方法中查看默认值用于无效比较的位置:

def _comp_method_FRAME(cls, func, special):
    str_rep = _get_opstr(func, cls)
    op_name = _get_op_name(func, special)

    @Appender('Wrapper for comparison method {name}'.format(name=op_name))
    def f(self, other):
        if isinstance(other, ABCDataFrame):
            # Another DataFrame
            if not self._indexed_same(other):
                raise ValueError('Can only compare identically-labeled '
                                 'DataFrame objects')
            return self._compare_frame(other, func, str_rep)

        elif isinstance(other, ABCSeries):
            return _combine_series_frame(self, other, func,
                                         fill_value=None, axis=None,
                                         level=None, try_cast=False)
        else:

            # straight boolean comparisons we want to allow all columns
            # (regardless of dtype to pass thru) See #4537 for discussion.
            res = self._combine_const(other, func,
                                      errors='ignore',
                                      try_cast=False)
            return res.fillna(True).astype(bool)

    f.__name__ = op_name
    return f

else 块是我们对标量情况感兴趣的块。

注意errors='ignore' 参数,这意味着无效的比较将返回NaN(而不是引发错误)。 res.fillna(True)True 填充这些失败的比较。

【讨论】:

  • 不保留 NaN 对我来说似乎是一个奇怪的设计决定。尤其是当一个字段没有合理的价值时,图书馆在其他地方大量使用 NaN。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-01-11
  • 2019-07-08
相关资源
最近更新 更多