Quiero convertir una tabla, representada como una lista de listas, en a 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 manera de especificar los tipos al convertir a DataFrame? ¿O es mejor crear el DataFrame primero y luego recorrer las columnas para cambiar el tipo de cada columna? Idealmente, me gustaría hacer esto de forma dinámica porque puede haber cientos de columnas y no quiero especificar exactamente qué columnas son de qué tipo. Todo lo que puedo garantizar es que cada columna contiene valores del mismo tipo.
df.apply(pd.to_numeric, downcast="integer", errors="ignore")
bajar columnas enteras al dtype más pequeño (entero) que contendrá los valores.Respuestas:
Tiene tres opciones principales para convertir tipos en pandas:
to_numeric()
- proporciona 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 le permite convertir a tipos categoriales (muy útil).infer_objects()
- un método de utilidad para convertir columnas de objetos que contienen objetos de Python a un tipo de pandas si es posible.Siga leyendo para obtener explicaciones más detalladas y el uso de cada uno de estos métodos.
1)
to_numeric()
La mejor manera de convertir una o más columnas de un DataFrame en valores numéricos es usar
pandas.to_numeric()
.Esta función intentará cambiar objetos no numéricos (como cadenas) en números enteros o números de coma 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 continuar usándola:
También puede usarlo para convertir varias columnas de un DataFrame a través del
apply()
método:Siempre y cuando todos sus valores se puedan convertir, eso es probablemente todo lo que necesita.
Manejo de errores
Pero, ¿qué pasa si algunos valores no se pueden convertir a un tipo numérico?
to_numeric()
también toma unerrors
argumento de palabra clave que le permite forzar valores no numéricosNaN
, o simplemente ignorar las columnas que contienen estos valores.Aquí hay un ejemplo usando una serie de cadenas
s
que tiene el tipo de objeto dtype:El comportamiento predeterminado es aumentar si no puede convertir un valor. En este caso, no puede hacer frente a la cadena 'pandas':
En lugar de fallar, podríamos querer que los pandas se consideren un valor numérico faltante / incorrecto. Podemos forzar valores no válidos de la
NaN
siguiente manera usando elerrors
argumento de la palabra clave:La tercera opción
errors
es simplemente ignorar la operación si se encuentra un valor no válido:Esta última opción es particularmente útil cuando desea convertir su DataFrame completo, pero no sabe cuál de nuestras columnas se puede convertir de manera confiable a un tipo numérico. En ese caso solo escribe:
La función se aplicará a cada columna del DataFrame. Las columnas que se pueden convertir a un tipo numérico se convertirán, mientras que las columnas que no se pueden (por ejemplo, que contienen cadenas o fechas sin dígitos) se dejarán solas.
Abatido
Por defecto, la conversión con
to_numeric()
le dará aint64
ofloat64
dtype (o cualquier ancho entero nativo de su plataforma).Por lo general, eso es lo que desea, pero ¿qué sucede si desea ahorrar algo de memoria y usar un tipo de letra más compacto, como
float32
, oint8
?to_numeric()
le da la opción de bajar a 'entero', 'firmado', 'sin signo', 'flotante'. Aquí hay un ejemplo para una serie simples
de tipo entero:Downcasting a 'integer' usa el entero más pequeño posible que puede contener los valores:
Downcasting to 'float' también elige un tipo flotante más pequeño de lo normal:
2)
astype()
El
astype()
método le permite ser explícito sobre el tipo de letra que desea que tenga su DataFrame o Series. Es muy versátil ya que puedes probar y pasar de un tipo a otro.Uso básico
Simplemente elija un tipo: puede usar un tipo de letra NumPy (por ejemplo
np.int16
), algunos tipos de Python (por ejemplo, bool) o tipos específicos de pandas (como el tipo de letra categórico).Llame al método en el objeto que desea convertir e
astype()
intentará convertirlo por usted:Observe que dije "probar": si
astype()
no sabe cómo convertir un valor en la Serie o el Marco de datos, generará 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 se puede suprimir al pasar
errors='ignore'
. Su objeto original será devuelto intacto.Ten cuidado
astype()
es poderoso, pero a veces convertirá valores "incorrectamente". Por ejemplo:Estos son enteros pequeños, entonces, ¿qué tal si se convierte a un tipo de 8 bits sin signo para ahorrar memoria?
¡La conversión funcionó, pero el -7 se envolvió para convertirse en 249 (es decir, 2 8 - 7)!
Intentar bajar el uso usando en su
pd.to_numeric(s, downcast='unsigned')
lugar podría ayudar a prevenir este error.3)
infer_objects()
La versión 0.21.0 de pandas introdujo el método
infer_objects()
para convertir columnas de un DataFrame que tienen un tipo de datos de objeto a un tipo más específico (conversiones suaves).Por ejemplo, aquí hay un DataFrame con dos columnas de tipo de objeto. Uno contiene enteros reales y el otro contiene cadenas que representan enteros:
Utilizando
infer_objects()
, puede cambiar el tipo de columna 'a' a int64:La columna 'b' se ha dejado sola ya que sus valores eran cadenas, no enteros. Si desea tratar de forzar la conversión de ambas columnas a un tipo entero, puede usar
df.astype(int)
en su lugar.fuente
.convert_objects
está depravado desde0.17
- usedf.to_numeric
en su lugarpd.to_numeric
y sus métodos complementarios solo funcionarán en una columna a la vez, a diferenciaconvert_objects
. La discusión sobre una función de reemplazo en la API parece estar en curso ; Espero que se mantenga un método que funcione en todo el DataFrame porque es muy útil.int64
aint32
?astype
(como en la otra respuesta), es decir.astype(numpy.int32)
.¿Qué tal esto?
fuente
pd.DataFrame
tiene undtype
argumento que podría permitirte hacer lo que estás buscando. df = pd.DataFrame (a, columnas = ['uno', 'dos', 'tres'], dtype = float) In [2]: df.dtypes Out [2]: un objeto dos float64 tres float64 dtype: objetoSettingWithCopyWarning: A value is trying to be set on a copy of a slice from a DataFrame. Try using .loc[row_index,col_indexer] = value instead
. Esto puede haberse introducido en una versión más nueva de pandas y, como resultado, no veo nada malo, pero me pregunto de qué se trata esta advertencia. ¿Alguna idea?ValueError: Cannot convert NA to integer
df = pd.DataFrame(a, columns=['one', 'two', 'three'], dtype={'one': str, 'two': int, 'three': float})
. Sin embargo, me resulta difícil encontrar la especificación para los valores "dtype" aceptados. Una lista estaría bien (actualmente lo hagodict(enumerate(my_list))
).El siguiente código cambiará el tipo de datos de la columna.
en lugar del tipo de datos, puede dar su tipo de datos. ¿Qué desea, como str, float, int, etc.
fuente
bool
, todo cambia aTrue
.Cuando solo necesito especificar columnas específicas, y quiero ser explícito, he usado (por DOCS LOCATION ):
Entonces, usando la pregunta original, pero proporcionándole nombres de columna ...
fuente
Aquí hay una función que toma como argumentos un DataFrame y una lista de columnas y coacciona todos los datos de las columnas a números.
Entonces, para su ejemplo:
fuente
¿Qué tal crear dos marcos de datos, cada uno con diferentes tipos de datos para sus columnas, y luego agregarlos juntos?
Resultados
Después de crear el marco de datos, puede rellenarlo con variables de punto flotante en la primera columna y cadenas (o cualquier tipo de datos que desee) en la segunda columna.
fuente
pandas> = 1.0
Aquí hay un cuadro que resume algunas de las conversiones más importantes en pandas.
Las conversiones a cadenas son triviales
.astype(str)
y no se muestran en la figura.Conversiones "duras" versus "suaves"
Tenga en cuenta que las "conversiones" en este contexto podrían referirse a la conversión de datos de texto en su tipo de datos real (conversión de hardware) o inferir tipos de datos más apropiados para los datos en columnas de objeto (conversión de software). Para ilustrar la diferencia, eche un vistazo a
fuente
Pensé que tenía el mismo problema, pero en realidad tengo una ligera diferencia que hace que el problema sea más fácil de resolver. Para otros que miran esta pregunta, vale la pena verificar el formato de su lista de entrada. En mi caso, los números son inicialmente flotantes, no cadenas como en la pregunta:
pero al procesar la lista demasiado antes de crear el marco de datos, pierdo los tipos y todo se convierte en una cadena.
Crear el marco de datos a través de una matriz numpy
da el mismo marco de datos que en la pregunta, donde las entradas en las columnas 1 y 2 se consideran cadenas. Sin embargo haciendo
en realidad da un marco de datos con las columnas en el formato correcto
fuente
A partir de pandas 1.0.0, tenemos
pandas.DataFrame.convert_dtypes
. ¡Incluso puedes controlar qué tipos convertir!fuente