Asignar tipos de datos pandas dataframe

Quiero configurar el dtype s de varias columnas en pd.Dataframe (tengo un archivo que he tenido que analizar manualmente en una lista de listas, ya que el archivo no era susceptible de pd.read_csv )

 import pandas as pd print pd.DataFrame([['a','1'],['b','2']], dtype={'x':'object','y':'int'}, columns=['x','y']) 

yo obtengo

 ValueError: entry not a 2- or 3- tuple 

La única forma en que puedo establecerlos es haciendo un bucle a través de cada variable de columna y astype con astype .

 dtypes = {'x':'object','y':'int'} mydata = pd.DataFrame([['a','1'],['b','2']], columns=['x','y']) for c in mydata.columns: mydata[c] = mydata[c].astype(dtypes[c]) print mydata['y'].dtype #=> int64 

¿Hay alguna manera mejor?

Desde 0.17, tienes que usar las conversiones explícitas:

 pd.to_datetime, pd.to_timedelta and pd.to_numeric 

(Como se menciona a continuación, no más “magic”, convert_objects ha quedado en desuso en 0.17)

 df = pd.DataFrame({'x': {0: 'a', 1: 'b'}, 'y': {0: '1', 1: '2'}, 'z': {0: '2018-05-01', 1: '2018-05-02'}}) df.dtypes x object y object z object dtype: object df xyz 0 a 1 2018-05-01 1 b 2 2018-05-02 

Puedes aplicar estos a cada columna que quieras convertir:

 df["y"] = pd.to_numeric(df["y"]) df["z"] = pd.to_datetime(df["z"]) df xyz 0 a 1 2018-05-01 1 b 2 2018-05-02 df.dtypes x object y int64 z datetime64[ns] dtype: object 

y confirme que el dtype esta actualizado.


RESPUESTA ANTIGUA / DEPRECADA para pandas 0.12 – 0.16: Puedes usar convert_objects para inferir mejores tipos de datos:

 In [21]: df Out[21]: xy 0 a 1 1 b 2 In [22]: df.dtypes Out[22]: x object y object dtype: object In [23]: df.convert_objects(convert_numeric=True) Out[23]: xy 0 a 1 1 b 2 In [24]: df.convert_objects(convert_numeric=True).dtypes Out[24]: x object y int64 dtype: object 

¡Mágico! (Triste de verlo en desuso).

Para aquellos que vienen de Google (etc.) como yo:

convert_objects ha quedado en desuso desde la convert_objects 0.17; si lo usas, obtendrás una advertencia como esta:

 FutureWarning: convert_objects is deprecated. Use the data-type specific converters pd.to_datetime, pd.to_timedelta and pd.to_numeric. 

Deberías hacer algo como lo siguiente:

  • df = df.astype(np.float)
  • df["A"] = pd.to_numeric(df["A"])

puede establecer los tipos explícitamente con pandas DataFrame.astype(dtype, copy=True, raise_on_error=True, **kwargs) y pasar un diccionario con los dtypes que desea dtype

Aquí hay un ejemplo:

 import pandas as pd wheel_number = 5 car_name = 'jeep' minutes_spent = 4.5 # set the columns data_columns = ['wheel_number', 'car_name', 'minutes_spent'] # create an empty dataframe data_df = pd.DataFrame(columns = data_columns) df_temp = pd.DataFrame([[wheel_number, car_name, minutes_spent]],columns = data_columns) data_df = data_df.append(df_temp, ignore_index=True) In [11]: data_df.dtypes Out[11]: wheel_number float64 car_name object minutes_spent float64 dtype: object data_df = data_df.astype(dtype= {"wheel_number":"int64", "car_name":"object","minutes_spent":"float64"}) 

ahora puedes ver que ha cambiado

 In [18]: data_df.dtypes Out[18]: wheel_number int64 car_name object minutes_spent float64 

Otra forma de configurar los tipos de columna es construir primero una matriz de registros numpy con los tipos deseados, completarla y luego pasarla a un constructor de DataFrame.

 import pandas as pd import numpy as np x = np.empty((10,), dtype=[('x', np.uint8), ('y', np.float64)]) df = pd.DataFrame(x) df.dtypes -> x uint8 y float64 

frente a un problema similar a usted. En mi caso, tengo miles de archivos de registros de Cisco que necesito analizar manualmente.

Para ser flexible con los campos y los tipos, he probado con éxito el uso de StringIO + read_cvs que, de hecho, acepta un dictado para la especificación de tipo de dtype.

Por lo general, obtengo cada uno de los archivos (5k-20k líneas) en un búfer y creo los diccionarios dtype dinámicamente.

Finalmente, concatené (con categórico … gracias a 0.19) estos marcos de datos en un dataframe grande que vuelco en hdf5.

Algo en este sentido

 import pandas as pd import io output = io.StringIO() output.write('A,1,20,31\n') output.write('B,2,21,32\n') output.write('C,3,22,33\n') output.write('D,4,23,34\n') output.seek(0) df=pd.read_csv(output, header=None, names=["A","B","C","D"], dtype={"A":"category","B":"float32","C":"int32","D":"float64"}, sep="," ) df.info()  RangeIndex: 5 entries, 0 to 4 Data columns (total 4 columns): A 5 non-null category B 5 non-null float32 C 5 non-null int32 D 5 non-null float64 dtypes: category(1), float32(1), float64(1), int32(1) memory usage: 205.0 bytes None 

No muy python … pero hace el trabajo.

Espero eso ayude.

JC

Es mejor utilizar np.arrays con tipo, y luego pasar los datos y los nombres de las columnas como un diccionario.

 import numpy as np import pandas as pd # Feature: np arrays are 1: efficient, 2: can be pre-sized x = np.array(['a', 'b'], dtype=object) y = np.array([ 1 , 2 ], dtype=np.int32) df = pd.DataFrame({ 'x' : x, # Feature: column name is near data array 'y' : y, } )