Antes de los pandas 1.0 (bueno, 0.25 en realidad) esta era la forma de facto de declarar una Serie / columna como una cadena:
# 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')
Desde pandas 1.0 en adelante, considere usar el "string"
tipo en su lugar.
# pandas >= 1.0
s = pd.Series(['a', 'b', 'c'], dtype="string")
s.dtype
# StringDtype
He aquí por qué, como lo citan los documentos:
Puede almacenar accidentalmente una mezcla de cadenas y no cadenas en una matriz dtype de objeto. Es mejor tener un tipo dedicado.
object
dtype rompe operaciones específicas de dtype como DataFrame.select_dtypes()
. No hay una manera clara de seleccionar solo texto mientras se excluyen las columnas que no son de texto pero que siguen siendo de tipo objeto
Al leer el código, el contenido de una object
matriz dtype es menos claro que 'string'
.
Consulte también la sección sobre Diferencias de comportamiento entre "string"
yobject
.
Los tipos de extensión (introducidos en 0.24 y formalizados en 1.0) están más cerca de los pandas que numpy, lo cual es bueno porque los tipos de numpy no son lo suficientemente potentes. Por ejemplo, NumPy no tiene ninguna forma de representar datos faltantes en datos enteros (desde type(NaN) == float
). Pero los pandas pueden usar columnas de enteros anulables .
¿Por qué debería dejar de usarlo?
Mezcla accidental de dtypes
La primera razón, como se describe en los documentos, es que puede almacenar accidentalmente datos que no son de texto en columnas de objetos.
# 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.
Desafiando diferenciar cadenas y otros objetos de python
Otro ejemplo de ejemplo obvio es que es más difícil distinguir entre "cadenas" y "objetos". Los objetos son esencialmente el tipo de cobertura para cualquier tipo que no admite operaciones vectorizables .
Considerar,
# 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
Hasta los pandas 0.25, prácticamente no había forma de distinguir que "A" y "B" no tienen el mismo tipo de datos.
# 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
De pandas 1.0, esto se vuelve mucho más simple:
# 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
Legibilidad
Esto se explica por sí mismo ;-)
OK, ¿debería dejar de usarlo ahora?
...No. Al momento de escribir esta respuesta (versión 1.1), no hay beneficios de rendimiento, pero los documentos esperan que las mejoras futuras mejoren significativamente el rendimiento y reduzcan el uso de memoria para las "string"
columnas en lugar de los objetos. Dicho esto, sin embargo, ¡nunca es demasiado temprano para formar buenos hábitos!
astype("string")
lugar deastype(str)
por muy buenas razones, eche un vistazo.