Usuario anónimo
Cambiar el tipo de datos de las columnas en Pandas
Quiero convertir una tabla, representada como una lista de listas, en un Pandas DataFrame. Como un ejemplo extremadamente simplificado:
a = [['a', '1.2', '4.2'], ['b', '70', '0.03'], ['x', '5', '0']]
df = pd.DataFrame(a)
¿Cuál es la mejor manera de convertir las columnas a los tipos apropiados, en este caso las columnas 2 y 3 en flotantes? ¿Hay alguna forma de especificar los tipos mientras se convierte a DataFrame? ¿O es mejor crear primero el DataFrame y luego recorrer las columnas para cambiar el tipo de cada columna? Lo ideal sería hacer esto de forma dinámica porque puede haber cientos de columnas y no quiero especificar exactamente qué columnas son de qué tipo. Lo único que puedo garantizar es que cada columna contenga valores del mismo tipo.
683
3
Tienes tres opciones principales para convertir tipos en pandas:
to_numeric()
- proporciona una funcionalidad para convertir de forma segura tipos no numéricos (por ejemplo, cadenas) a un tipo numérico adecuado. (Ver tambiénto_datetime()
yto_timedelta()
.)astype()
- convierte (casi) cualquier tipo a (casi) cualquier otro tipo (incluso si no es necesariamente sensato hacerlo). También permite convertir a tipos categoriales (muy útil).infer_objects()
- un método de utilidad para convertir columnas de objetos de Python a un tipo de pandas si es posible. Siga leyendo para ver explicaciones más detalladas y el uso de cada uno de estos métodos.1.
a_numérico()
La mejor manera de convertir una o más columnas de un DataFrame a valores numéricos es utilizar
pandas.to_numeric()
. Esta función intentará cambiar los objetos no numéricos (como las cadenas) en enteros o números de punto flotante, según corresponda.Uso básico
La entrada a
to_numeric()
es una Serie o una sola columna de un DataFrame.Como puede ver, se devuelve una nueva Serie. Recuerde asignar esta salida a una variable o nombre de columna para seguir utilizándola:
También se puede utilizar para convertir múltiples columnas de un DataFrame a través del método
apply()
:Mientras tus valores puedan ser convertidos todos, eso es probablemente todo lo que necesitas.
Manejo de errores
¿Pero qué pasa si algunos valores no pueden ser convertidos a un tipo numérico?
to_numeric()
también toma un argumento de palabra claveerrors
que le permite forzar los valores no numéricos a serNaN
, o simplemente ignorar las columnas que contienen estos valores. Aquí hay un ejemplo usando una serie de cadenass
que tiene el objeto dtype:El comportamiento por defecto es levantar si no puede convertir un valor. En este caso, no puede con la cadena
pandas
:En lugar de fallar, podríamos querer que 'pandas' se considere un valor numérico no válido. Podemos coaccionar los valores no válidos a
NaN
de la siguiente manera utilizando el argumento de la palabra claveerrors
:La tercera opción para
errors
es simplemente ignorar la operación si se encuentra un valor no válido:Esta última opción es especialmente útil cuando se quiere convertir todo el DataFrame, pero no se sabe cuáles de nuestras columnas se pueden convertir de forma fiable a un tipo numérico. En ese caso basta con escribir
La función se aplicará a cada columna del DataFrame. Las columnas que puedan ser convertidas a un tipo numérico serán convertidas, mientras que las columnas que no puedan (por ejemplo, que contengan cadenas no numéricas o fechas) se dejarán como están.
Downcasting
Por defecto, la conversión con
to_numeric()
le dará un tipoint64
ofloat64
(o cualquier ancho de entero nativo de su plataforma). Eso es normalmente lo que quieres, pero ¿qué pasa si quieres ahorrar algo de memoria y usar un tipo más compacto, comofloat32
, oint8
?to_numeric()
te da la opción de convertirlo en "entero", "con signo", "sin signo" o "float". Aquí hay un ejemplo para una serie simples
de tipo entero:Al pasar a 'integer' se utiliza el menor entero posible que pueda contener los valores:
El downcasting a 'float' elige de forma similar un tipo flotante más pequeño de lo normal:
2.
astype()
El método
astype()
te permite ser explícito sobre el tipo que quieres que tenga tu DataFrame o Serie. Es muy versátil en el sentido de que puedes intentar pasar de un tipo a otro cualquiera.Uso básico
Sólo tienes que elegir un tipo: puedes usar un dtype de NumPy (por ejemplo
np.int16
), algunos tipos de Python (por ejemplo bool), o tipos específicos de pandas (como el dtype categorical). Llame al método en el objeto que desea convertir yastype()
tratará de convertirlo por usted:Fíjate que he dicho "intentar" - si
astype()
no sabe cómo convertir un valor en la Serie o DataFrame, dará un error. Por ejemplo, si tiene un valorNaN
oinf
obtendrá un error al intentar convertirlo en un entero. A partir de pandas 0.20.0, este error puede suprimirse pasandoerrors='ignore'
. Su objeto original se devolverá intacto.Tenga cuidado
astype()
es potente, pero a veces convierte valores "incorrectamente". Por ejemplo:Estos son enteros pequeños, así que ¿qué tal si se convierte a un tipo de 8 bits sin signo para ahorrar memoria?
La conversión funcionó, pero el -7 se redondeó para convertirse en 249 (es decir, 28 - 7). Intentar la conversión hacia abajo usando
pd.to_numeric(s, downcast='unsigned')
podría ayudar a prevenir este error.3.
inferir_objetos()
La versión 0.21.0 de pandas introdujo el método
infer_objects()
para convertir las columnas de un DataFrame que tienen un tipo de dato de objeto a un tipo más específico (conversiones suaves). Por ejemplo, aquí tenemos un DataFrame con dos columnas de tipo objeto. Una contiene números enteros reales y la otra contiene cadenas que representan números enteros:Usando
infer_objects()
, puedes cambiar el tipo de la columna 'a' a int64:La columna 'b' se ha dejado sola ya que sus valores eran cadenas, no enteros. Si quieres forzar la conversión de ambas columnas a un tipo entero, puedes utilizar
df.astype(int)
en su lugar.¿Qué te parece esto?
Esta es una función que toma como argumentos un DataFrame y una lista de columnas y convierte todos los datos de las columnas en números.
Así, para su ejemplo: