¿Por qué Pandas me dice que tengo objetos, aunque cada elemento de la columna seleccionada es una cadena, incluso después de una conversión explícita?
Este es mi DataFrame:
<class 'pandas.core.frame.DataFrame'>
Int64Index: 56992 entries, 0 to 56991
Data columns (total 7 columns):
id 56992 non-null values
attr1 56992 non-null values
attr2 56992 non-null values
attr3 56992 non-null values
attr4 56992 non-null values
attr5 56992 non-null values
attr6 56992 non-null values
dtypes: int64(2), object(5)
Cinco de ellos lo son dtype object
. Convierto explícitamente esos objetos en cadenas:
for c in df.columns:
if df[c].dtype == object:
print "convert ", df[c].name, " to string"
df[c] = df[c].astype(str)
Entonces, df["attr2"]
todavía tiene dtype object
, aunque type(df["attr2"].ix[0]
revela str
, lo que es correcto.
Pandas distingue entre int64
y float64
y object
. ¿Cuál es la lógica detrás de esto cuando no hay dtype str
? ¿Por qué está str
cubierto por object
?
Respuestas:
El objeto dtype proviene de NumPy, describe el tipo de elemento en un ndarray. Todos los elementos de un ndarray deben tener el mismo tamaño en bytes. Para int64 y float64, son 8 bytes. Pero para las cuerdas, la longitud de la cuerda no es fija. Entonces, en lugar de guardar los bytes de cadenas en el ndarray directamente, Pandas usa object ndarray, que guarda punteros a objetos, debido a esto, el dtype de este tipo ndarray es object.
Aquí hay un ejemplo:
fuente
La respuesta aceptada es buena. Solo quería proporcionar una respuesta que hiciera referencia a la documentación . La documentación dice:
Como dice el comentario principal "No se preocupe, se supone que debe ser así". (Aunque la respuesta aceptada hizo un gran trabajo al explicar el "por qué"; las cadenas son de longitud variable)
fuente
astype(str)
aunque todavía me pregunto si la conversión de cadenas es necesariaLa respuesta de @ HYRY es genial. Solo quiero proporcionar un poco más de contexto ...
Arrays almacenan datos como contiguos , de tamaño fijo bloques de memoria. La combinación de estas propiedades juntas es lo que hace que los arreglos sean increíblemente rápidos para el acceso a los datos. Por ejemplo, considere cómo su equipo puede almacenar una matriz de enteros de 32 bits,
[3,0,1]
.Si le pide a su computadora que busque el tercer elemento en la matriz, comenzará desde el principio y luego saltará a través de 64 bits para llegar al tercer elemento. Saber exactamente cuántos bits atravesar es lo que hace que las matrices sean rápidas .
Ahora considere la secuencia de cadenas
['hello', 'i', 'am', 'a', 'banana']
. Las cadenas son objetos que varían en tamaño, por lo que si intentara almacenarlos en bloques de memoria contiguos, terminaría luciendo así.Ahora su computadora no tiene una forma rápida de acceder a un elemento solicitado al azar. La clave para superar esto es utilizar punteros. Básicamente, almacene cada cadena en una ubicación de memoria aleatoria y llene la matriz con la dirección de memoria de cada cadena. (Las direcciones de memoria son solo números enteros). Así que ahora, las cosas se ven así
Ahora, si le pide a su computadora que busque el tercer elemento, como antes, puede saltar 64 bits (asumiendo que las direcciones de memoria son enteros de 32 bits) y luego dar un paso adicional para ir a buscar la cadena.
El desafío para NumPy es que no hay garantía de que los punteros apunten realmente a cadenas. Es por eso que informa el dtype como 'objeto'.
Desvergonzadamente voy a conectar mi propio artículo de blog donde originalmente discutí esto.
fuente
A partir de la versión 1.0.0 (enero de 2020), pandas se introdujo como una característica experimental que brinda soporte de primera clase para los tipos de cadenas
pandas.StringDtype
.Si bien seguirá viendo
object
de forma predeterminada, el nuevo tipo se puede usar especificando unadtype
depd.StringDtype
o simplemente'string'
:fuente
The implementation may change without warning.
que significa que las nuevas actualizaciones romperán sus programas antiguos.