我有一个数据框,其中包含x
和v
等复选标记,我将使用以下行替换为布尔值:
df.replace({'v': True, 'x': False}, inplace=True)
在运行df.replace()
之前,根据df.dtypes
的所有列的类型为object
。在replace()
之后,所有其他列仍为object
,但单个列的类型为bool,其中的值为numpy.bool_
类型。 Pycharm显示此特定列,红色背景为True值,如下所示。
为什么会发生这种情况? object
不适合存储布尔值吗?为什么pandas
会将dtype
从object
更改为bool
?究竟是什么控制它以及如何强制将dtype保持为object
?
是否有理由将所有列改为pandas.np.bool
,例如出于性能原因?
答案 0 :(得分:3)
Pandas在内部将系列存储为NumPy阵列。当一个系列具有混合类型时,Pandas / NumPy必须做出决定:它选择一个包含该系列中所有类型的类型。作为一个简单的示例,如果您有一系列类型为int
的整数并将单个值更改为float
,则系列将变为float
类型。
在此示例中,您的第0和第2个系列的值为NaN
。现在NaN
或np.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 == 1
和False == 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