renombrar - pandas python
Cambiar el tipo de datos de las columnas en Pandas. (6)
¿Qué tal crear dos marcos de datos, cada uno con diferentes tipos de datos para sus columnas, y luego agregarlos juntos?
d1 = pd.DataFrame(columns=[ ''float_column'' ], dtype=float)
d1 = d1.append(pd.DataFrame(columns=[ ''string_column'' ], dtype=str))
Resultados
In[8}: d1.dtypes
Out[8]:
float_column float64
string_column object
dtype: object
Después de crear el marco de datos, puede poblarlo con variables de punto flotante en la primera columna y cadenas (o cualquier tipo de datos que desee) en la segunda columna.
Quiero convertir una tabla, representada como una lista de listas, en un DataFrame de Pandas. 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 una 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.
¿Qué tal esto?
a = [[''a'', ''1.2'', ''4.2''], [''b'', ''70'', ''0.03''], [''x'', ''5'', ''0'']]
df = pd.DataFrame(a, columns=[''one'', ''two'', ''three''])
df
Out[16]:
one two three
0 a 1.2 4.2
1 b 70 0.03
2 x 5 0
df.dtypes
Out[17]:
one object
two object
three object
df[[''two'', ''three'']] = df[[''two'', ''three'']].astype(float)
df.dtypes
Out[19]:
one object
two float64
three float64
Aquí hay una función que toma como argumentos un DataFrame y una lista de columnas y obliga a que todos los datos de las columnas sean números.
# df is the DataFrame, and column_list is a list of columns as strings (e.g ["col1","col2","col3"])
# dependencies: pandas
def coerce_df_columns_to_numeric(df, column_list):
df[column_list] = df[column_list].apply(pd.to_numeric, errors=''coerce'')
Por lo tanto, para su ejemplo:
import pandas as pd
def coerce_df_columns_to_numeric(df, column_list):
df[column_list] = df[column_list].apply(pd.to_numeric, errors=''coerce'')
a = [[''a'', ''1.2'', ''4.2''], [''b'', ''70'', ''0.03''], [''x'', ''5'', ''0'']]
df = pd.DataFrame(a, columns=[''col1'',''col2'',''col3''])
coerce_df_columns_to_numeric(df, [''col2'',''col3''])
Cuando solo he necesitado especificar columnas específicas y quiero ser explícito, he usado (según astype() ):
dataframe = dataframe.astype({''col_name_1'':''int'',''col_name_2'':''float64'', etc. ...})
Entonces, usando la pregunta original, pero proporcionándole nombres de columna ...
a = [[''a'', ''1.2'', ''4.2''], [''b'', ''70'', ''0.03''], [''x'', ''5'', ''0'']]
df = pd.DataFrame(a, columns=[''col_name_1'', ''col_name_2'', ''col_name_3''])
df = df.astype({''col_name_2'':''float64'', ''col_name_3'':''float64''})
Este código a continuación cambiará el tipo de datos de la columna.
df[[''col.name1'', ''col.name2''...]] = df[[''col.name1'', ''col.name2''..]].astype(''data_type'')
en lugar del tipo de datos, puede dar su tipo de datos. ¿Qué desea como str, float, int etc.?
Tienes tres opciones principales para convertir tipos en pandas.
1. to_numeric()
La mejor manera de convertir una o más columnas de un DataFrame a valores numéricos es usar pandas.to_numeric()
.
Uso básico
La entrada a to_numeric()
es una serie o una sola columna. Se devuelve una nueva Serie, así que recuerde asignar la salida a una variable:
# convert Series
my_series = pd.to_numeric(my_series)
# convert column "a" of a DataFrame
df["a"] = pd.to_numeric(df["a"])
También puede usarlo para convertir varias columnas de un DataFrame a través de apply
:
# convert all columns of DataFrame
df = df.apply(pd.to_numeric) # convert all columns of DataFrame
# convert just columns "a" and "b"
df[["a", "b"]] = df[["a", "b"]].apply(pd.to_numeric)
Mientras 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 un argumento de palabra clave de errors
que le permite forzar a los valores no numéricos a ser NaN
, o simplemente ignorar las columnas que contienen estos valores.
Aquí hay un ejemplo utilizando una serie de cadenas s
que tiene el tipo de objeto:
>>> s = pd.Series([''1'', ''2'', ''4.7'', ''pandas'', ''10''])
>>> s
0 1
1 2
2 4.7
3 pandas
4 10
dtype: object
El comportamiento predeterminado es aumentar si no puede convertir un valor. En este caso, no puede hacer frente a la cadena ''pandas'':
>>> pd.to_numeric(s) # or pd.to_numeric(s, errors=''raise'')
ValueError: Unable to parse string
En lugar de fallar, podríamos querer que ''pandas'' se considere un valor numérico faltante / malo. Podemos forzar valores no válidos a NaN
siguiente manera:
>>> pd.to_numeric(s, errors=''coerce'')
0 1.0
1 2.0
2 4.7
3 NaN
4 10.0
dtype: float64
La tercera opción para errors
es simplemente ignorar la operación si se encuentra un valor no válido:
>>> pd.to_numeric(s, errors=''ignore'')
# the original Series is returned untouched
Esta última opción es particularmente útil cuando desea convertir todo su DataFrame, pero no sabe cuál de nuestras columnas se puede convertir de manera confiable a un tipo numérico. En ese caso solo escribe:
df.apply(pd.to_numeric, errors=''ignore'')
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 pueden (por ejemplo, contienen cadenas o fechas sin dígitos) se dejarán solas.
Downcasting
De manera predeterminada, la conversión con to_numeric()
le dará un int64
o float64 (o cualquier ancho de entero que sea nativo de su plataforma).
Eso suele ser lo que quieres, pero ¿qué sucede si quieres guardar algo de memoria y usar un tipo de letra más compacto, como float32
o int8
?
to_numeric()
te da la opción de cambiar a ''entero'', ''firmado'', ''sin firmar'', ''flotar''. Aquí hay un ejemplo para una serie simple s
de tipo entero:
>>> s = pd.Series([1, 2, -7])
>>> s
0 1
1 2
2 -7
dtype: int64
La reducción a ''entero'' usa el entero más pequeño posible que puede contener los valores:
>>> pd.to_numeric(s, downcast=''integer'')
0 1
1 2
2 -7
dtype: int8
La reducción a ''flotar'' de manera similar elige un tipo flotante más pequeño que el normal:
>>> pd.to_numeric(s, downcast=''float'')
0 1.0
1 2.0
2 -7.0
dtype: float32
2. astype()
El método astype()
permite ser explícito sobre el tipo de dato que desea que tenga su DataFrame o Series. Es muy versátil, ya que puedes intentar ir de un tipo a otro.
Uso básico
Simplemente elija un tipo: puede usar un tipo de tipo NumPy (por ejemplo, np.int16
), algunos tipos de Python (por ejemplo, bool) o tipos específicos de pandas (como el tipo de código categórico).
Llame al método del objeto que desea convertir y astype()
intentará convertirlo por usted:
# convert all DataFrame columns to the int64 dtype
df = df.astype(int)
# convert column "a" to int64 dtype and "b" to complex type
df = df.astype({"a": int, "b": complex})
# convert Series to float16 type
s = s.astype(np.float16)
# convert Series to Python strings
s = s.astype(str)
# convert Series to categorical type - see docs for more details
s = s.astype(''category'')
Observe que dije "intentar": si astype
no sabe cómo convertir un valor en Series o DataFrame, generará un error. Por ejemplo, si tiene un valor NaN
o inf
, obtendrá un error al intentar convertirlo en un entero.
A partir de los pandas 0.20.0, este error se puede suprimir pasando errors=''ignore''
. Su objeto original será devuelto sin tocar.
Ten cuidado
astype()
es poderoso, pero a veces convierte los valores "incorrectamente". Por ejemplo:
>>> s = pd.Series([1, 2, -7])
>>> s
0 1
1 2
2 -7
dtype: int64
Estos son enteros muy pequeños, entonces, ¿qué hay de convertir a un tipo de 8 bits sin firmar?
>>> s.astype(np.uint8)
0 1
1 2
2 249
dtype: uint8
¡La conversión funcionó, pero el -7 se redondeó para convertirse en 249 (es decir, 2 8 - 7)!
Intentar hacer un pd.to_numeric(s, downcast=''unsigned'')
usando pd.to_numeric(s, downcast=''unsigned'')
podría ayudar a prevenir este error.
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 de software).
Por ejemplo, aquí se crea un DataFrame con dos columnas de tipo de objeto. Uno contiene números enteros reales y el otro contiene cadenas que representan números enteros:
>>> df = pd.DataFrame({''a'': [7, 1, 5], ''b'': [''3'',''2'',''1'']}, dtype=''object'')
>>> df.dtypes
a object
b object
dtype: object
Usando infer_objects()
, puedes cambiar el tipo de columna ''a'' a int64:
>>> df = df.infer_objects()
>>> df.dtypes
a int64
b object
dtype: object
La columna ''b'' se ha dejado sola ya que sus valores eran cadenas, no enteros. Si quisiera probar y forzar la conversión de ambas columnas a un tipo entero, podría usar df.astype(int)
lugar.