【问题标题】:Pandas: replacement with boolean values gives inconsistent resultsPandas:用布尔值替换会产生不一致的结果
【发布时间】:2018-11-20 03:56:31
【问题描述】:

我有一个数据框,其中包含 xv 之类的复选标记,我将用以下行替换为布尔值:

df.replace({'v': True, 'x': False}, inplace=True)

在运行df.replace() 之前,根据df.dtypes 的所有列的类型是object。在replace() 之后,所有其他列仍然是object,除了一个布尔类型的列,其中的值是numpy.bool_ 类型。 Pycharm 以红色背景显示该特定列,表示 True 值,如下所示。

为什么会发生这种情况? object 不适合存储布尔值吗?为什么pandas 将这一列的dtypeobject 更改为bool?究竟是什么控制它,我如何强制将 dtype 保持为object

是否有理由将所有列改为pandas.np.bool,例如出于性能原因?

【问题讨论】:

    标签: python pandas boolean


    【解决方案1】:

    Pandas 在内部将系列存储为 NumPy 数组。当一个系列有混合类型时,Pandas / NumPy 必须做出决定:它选择一个包含该系列中所有类型的类型。举个简单的例子,如果你有一系列 int 类型的整数并将单个值更改为 float,那么你的系列将变为 float 类型。

    在此示例中,您的第 0 和第 2 系列具有 NaN 值。现在NaNnp.nan 被认为是float(尝试type(np.nan),这将返回float),而True / False 被认为是布尔值。 NumPy 存储这些值的唯一方法是使用 dtype object,它只是一堆指针(很像列表)。

    另一方面,您的第一列只有布尔值,可以使用bool 类型存储。这里的好处是因为你没有使用指针集合 NumPy 可以为这个数组分配一个连续的内存块。这将产生相对于object 系列或list 的性能优势。

    您可以自己测试以上所有内容。以下是一些示例:

    s1 = pd.Series([True, False])
    print(s1.dtype)  # bool
    
    s2 = pd.Series([True, False, np.nan])
    print(s2.dtype)  # object
    
    s3 = pd.Series([True, False, 0, 1])
    print(s3.dtype)  # object
    

    最后一个例子很有趣,因为在 Python 中True == 1False == 0 都返回True,因为bool 可以被认为是int 的子类。因此,在内部,Pandas / NumPy 已决定不强制执行此相等性并选择其中一个。这样做的必然结果是,建议您在处理混合类型时检查您的系列的类型。

    另请注意,当您更新值时,Pandas 会检查 dtypes:

    s1 = pd.Series([True, 5.4])
    print(s1.dtype)  # object
    
    s1.iloc[-1] = False
    print(s1.dtype)  # bool
    

    【讨论】:

    • 但在这种情况下,所有列最初都被解析为objectpandas.pydata.org/pandas-docs/version/0.22/generated/… 的文档没有提到修改单元格会自动转换 dtype
    • @ccpizza,你说得对,文档中没有提到。但这是真的(我添加了一个额外的例子来说明)。我还添加了一些可能不明显的行为,即不等同于False == 0
    • 所以,例如,如果我想让所有列都设置为 bool 类型,有没有办法强制它,同时将无效单元格设置为 nan
    • 知道了。谢谢!
    • 好答案@jpp
    猜你喜欢
    • 1970-01-01
    • 2017-08-18
    • 2021-08-03
    • 2012-01-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多