如果您来到这里是想了解Pandas中'string'
和object
数据类型之间的区别,请阅读以下内容。截至Pandas 1.5.3,这两种数据类型有两个主要区别。
1. 空值处理
object
数据类型不仅可以存储字符串,还可以存储混合数据类型。因此,如果您想将值转换为字符串,则应使用astype(str)
方法。但是,这会将所有值都转换为字符串,即使NaN也会变成字面上的'nan'
字符串。而string
是一种可空数据类型,因此将其转换为'string'
会将NaN保留为null值。
x = pd.Series(['a', float('nan'), 1], dtype=object)
x.astype(str).tolist()
x.astype('string').tolist()
这导致对于
object
数据类型列进行的字符串操作(例如字符计数、比较),返回的结果是
numpy.int
或
numpy.bool
等,而对于
'string'
数据类型进行的相同操作则返回可为空的
pd.Int64
或
pd.Boolean
数据类型。特别地,对于
object
数据类型进行的 NaN 比较返回 False(因为 NaN 不等于任何值),而对于
'string'
数据类型进行的比较仍然保持为
pd.NA
。
x = pd.Series(['a', float('nan'), 'b'], dtype=object)
x == 'a'
0 True
1 False
2 False
dtype: bool
y = pd.Series(['a', float('nan'), 'b'], dtype='string')
y == 'a'
0 True
1 <NA>
2 False
dtype: boolean
因此,使用'string'
数据类型时,空值处理更加灵活,因为您可以调用fillna()
等方法来处理空值,以任何您想要的方式进行处理。1
2. 'string'
数据类型更清晰
如果一个pandas列是'object'
数据类型,则其中的值可以被替换为任何内容。例如,其中的字符串可以被整数替换,这是可以接受的(例如下面的x
)。但是,如果您期望其中的每个值都是字符串,则可能会在之后产生不必要的后果。'string'
数据类型没有这个问题,因为一个字符串只能被另一个字符串替换(例如下面的y
)。
x = pd.Series(['a', 'b'], dtype=str)
y = pd.Series(['a', 'b'], dtype='string')
x[1] = 3
y[1] = 3
y[1] = '3'
这样的好处在于您可以使用 select_dtypes()
来选择仅字符串列。换句话说,对于 object
数据类型,没有办法识别字符串列,但对于 'string'
数据类型可以。
df = pd.DataFrame({'A': ['a', 'b', 'c'], 'B': [[1], [2,3], [4,5]]}).astype({'A': 'string'})
df.select_dtypes('string')
A
0 a
1 b
2 c
df = pd.DataFrame({'A': ['a', 'b', 'c'], 'B': [[1], [2,3], [4,5]]})
df.select_dtypes('object')
A B
0 a [1]
1 b [2, 3]
2 c [4, 5]
3. 内存效率
字符串 Dtype 'string'
有存储选项(Python 和 PyArrow),如果字符串较短,则 PyArrow 的效率非常高。请看以下示例:
lst = np.random.default_rng().integers(1000000, size=1000).astype(str).tolist()
x = pd.Series(lst, dtype=object)
y = pd.Series(lst, dtype='string[pyarrow]')
x.memory_usage(deep=True)
y.memory_usage(deep=True)
正如您所看到的,如果字符串很短(在上面的示例中最多为6个字符),pyarrow消耗的内存要少6倍以上。然而,正如下面的示例所示,如果字符串很长,则几乎没有任何区别。
z = x * 1000
w = (y.astype(str) * 1000).astype('string[pyarrow]')
z.memory_usage(deep=True)
w.memory_usage(deep=True)
1类似的直觉已经存在于str.contains
,str.match
等中。
x = pd.Series(['a', float('nan'), 'b'], dtype=object)
x.str.match('a', na=np.nan)
0 True
1 NaN
2 False
dtype: object
numpy
中使用字符串数据类型,则基本上是一个定长的 c 语言风格字符串。在pandas
中,它们是“普通”的 Python 字符串,因此是对象类型。 - Joe Kington