如何将 pandas 中的类型转换为系列中带有“None”值的布尔值?

How to convert type to bool in pandas with `None` values in the series?

为什么值 None 在这个系列中同时转换为 TrueFalse

环境:

进口:

from IPython.display import display
import pandas as pd

None 转换为 True:

df_test1 = pd.DataFrame({'test_column':[0,1,None]})
df_test1['test_column'] = df_test1.test_column.astype(bool)
display(df_test1)

None 转换为 False:

df_test2 = pd.DataFrame({'test_column':[0,1,None,'test']})
df_test2['test_column'] = df_test2.test_column.astype(bool)
display(df_test2)

这是预期的行为吗?

不同之处在于数据类型 df_test1.prime_member.dtypefloat64,而您没有 None,而是 NaN。现在,bool(np.nan)True.

但是,当您有混合类型的列时:df_test2.prime_member.dtypeobject。那么None在数据中仍然是None,而bool(None)就是False.

是的,这是预期的行为,它从每个系列(列)的初始 dtype 存储类型开始。第一个输入结果是一系列 浮点数 ,第二个输入包含对 Python 对象 :

的引用
>>> pd.Series([0,1,None]).dtype
dtype('float64')
>>> pd.Series([0,1,None,'test']).dtype
dtype('O')

None 的 float 版本是 NaN,或者 Not a Number,在解释为布尔值时转换为 True(因为它不等于 0) :

>>> pd.Series([0,1,None])[2]
nan
>>> bool(pd.Series([0,1,None])[2])
True

在另一种情况下,原始 None 对象被保留,转换为 False:

>>> pd.Series([0,1,None,'test'])[2] is None
True
>>> bool(None)
False

所以这归结为自动类型推断,Pandas认为最适合每一列的类型;见DataFrame.infer_objects() method。目标是最小化存储需求和操作性能;将数字存储为本机 64 位浮点值会导致更快的数字运算和更小的内存占用,同时仍然能够将 'missing' 值表示为 NaN。

但是,当您混合传入数字和字符串时,Panda 无法使用专门的专用数组类型,因此会退回到“Python 对象”类型,这是对原始对象的引用Python 个对象。

您可以明确指定要使用的类型,而不是让 Pandas猜测您需要什么类型。您可以使用 nullable integer types 之一(使用 Pandas.NA 而不是 NaN);将这些转换为布尔值会导致缺失值转换为 False:

>>> pd.Series([0,1,None], dtype=pd.Int64Dtype).astype(bool)
0    False
1     True
2    False
dtype: bool

另一种选择是转换为 nullable boolean type,从而保留缺失数据的 None / NaN 指标:

>>> pd.Series([0,1,None]).astype("boolean")
0    False
1     True
2     <NA>
dtype: boolean

另请参阅 Working with missing data section in the user manual, as well as the nullable integer and nullable boolean 数据类型手册页。

请注意,NA 值的 Pandas 概念表示 缺失数据 ,在创建框架后 still considered experimental, which is why it is not yet the default. But if you want to 'opt in' for dataframes you just created, you can call the DataFrame.convert_dtypes() method

>>> df = pd.DataFrame({'prime_member':[0,1,None]}).convert_dtypes()
>>> df.prime_member
0       0
1       1
2    <NA>
Name: prime_member, dtype: Int64