pandas >= 1.0:是时候停止使用astype(str)了!
在pandas 1.0之前(嗯,实际上是0.25),这是将Series/column声明为字符串的实际方式:
# pandas <= 0.25
# Note to pedants: specifying the type is unnecessary since pandas will
# automagically infer the type as object
s = pd.Series(['a', 'b', 'c'], dtype=str)
s.dtype
# dtype('O')
从pandas 1.0开始,考虑使用“string”类型代替。
# pandas >= 1.0
s = pd.Series(['a', 'b', 'c'], dtype="string")
s.dtype
# StringDtype
以下是文档中引用的原因:
在对象dtype数组中,可能会意外地混合存储字符串和非字符串。最好有一个专用的dtype。
对象dtype中断特定于dtype的操作,如DataFrame.select_dtypes()。没有一个明确的方法来选择文本
排除非文本但仍然是对象类型的列。
读取代码时,对象dtype数组的内容没有'string'明确。
请参见“string”和object之间的行为差异。
扩展类型(在0.24中引入,在1.0中正式化)更接近于pandas而不是numpy,这很好,因为numpy类型不够强大。例如,NumPy没有任何方法来表示整数数据中的缺失数据(因为type(NaN) == float)。但是熊猫可以使用可空整数列。
为什么我应该停止使用它?
不小心混合了dtypes类型
第一个原因,如文档中所述,是您可能会意外地将非文本数据存储在对象列中。
# pandas <= 0.25
pd.Series(['a', 'b', 1.23]) # whoops, this should have been "1.23"
0 a
1 b
2 1.23
dtype: object
pd.Series(['a', 'b', 1.23]).tolist()
# ['a', 'b', 1.23] # oops, pandas was storing this as float all the time.
# pandas >= 1.0
pd.Series(['a', 'b', 1.23], dtype="string")
0 a
1 b
2 1.23
dtype: string
pd.Series(['a', 'b', 1.23], dtype="string").tolist()
# ['a', 'b', '1.23'] # it's a string and we just averted some potentially nasty bugs.
很难区分字符串和其他python对象
另一个明显的例子是很难区分“字符串”和“对象”。对象本质上是不支持可向量化操作的任何类型的通用类型。
考虑,
# Setup
df = pd.DataFrame({'A': ['a', 'b', 'c'], 'B': [{}, [1, 2, 3], 123]})
df
A B
0 a {}
1 b [1, 2, 3]
2 c 123
直到熊猫0.25,几乎没有办法区分“A”和“B”不具有相同类型的数据。
# pandas <= 0.25
df.dtypes
A object
B object
dtype: object
df.select_dtypes(object)
A B
0 a {}
1 b [1, 2, 3]
2 c 123
从pandas 1.0开始,这变得简单多了:
# pandas >= 1.0
# Convenience function I call to help illustrate my point.
df = df.convert_dtypes()
df.dtypes
A string
B object
dtype: object
df.select_dtypes("string")
A
0 a
1 b
2 c
可读性
这是不言而喻的;-)
好吧,那我现在应该停止使用它吗?
……没有。在写这个答案时(1.1版本),没有性能上的好处,但是文档希望未来的增强能够显著提高性能,并减少“字符串”列的内存使用,而不是对象。话虽如此,养成好习惯越早越好!