Quiero convertir una tabla, representado como una lista de listas, en una Pandas DataFrame. Como un ejemplo 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 adecuados, en este caso las columnas 2 y 3 en los flotadores? Es allí una manera de especificar los tipos, mientras que la conversión a DataFrame? O es mejor crear el DataFrame primero y luego el bucle a través de las columnas para cambiar el tipo de cada columna? Idealmente me gustaría hacer esto de una manera dinámica, porque no puede ser de cientos de columnas y no quiero especificar exactamente qué columnas se de que tipo. Todo lo que puedo garantizar es que cada una de las columnas contiene los valores del mismo tipo.

  • Para este particular, los datos df = pd.DataFrame(a, dtype='float') hizo el truco. No puedo pasar de una secuencia sin embargo, como una dtype.
  • El crudo se leen los datos de csv y es muy estructurado, es decir, las filas no tienen el mismo número de columnas. Es por eso que tuve que leer de ella con el IO funciones en lugar de la ep.read_csv.
  • Las filas que no tengan el mismo número de columnas también pueden no ser un problema en 0.11…
  • Usted debe considerar la aceptación de esta respuesta.
  • .convert_objects es depracated desde 0.17. Use the data-type specific converters pd.to_datetime, pd.to_timedelta and pd.to_numeric.
  • convert_objects ha quedado obsoleta desde 0,17 en favor de un tipo específico de funciones pd.to_datetime/ to_timestamp/ to_numeric. Por favor, puedes eliminar tu comentario? Especialmente esta cuestión ya se está convirtiendo en la canónica.

InformationsquelleAutor | 2013-04-08

7 Comentarios

  1. 884

    Usted tiene tres opciones principales para la conversión de tipos en los pandas:

    1. to_numeric() – proporciona funcionalidad de forma segura de no convertir los tipos numéricos (por ejemplo, cadenas) a un tipo numérico. (Ver también to_datetime() y to_timedelta().)

    2. astype() – convertir (casi) cualquier tipo a (casi) cualquier otro tipo (incluso si no es necesariamente sensible a hacerlo). También le permite convertir a categorial tipos (muy útil).

    3. infer_objects() – un método de utilidad para convertir objetos de columnas que sostienen los objetos de Python a un pandas tipo, si es posible.

    Leer para explicaciones más detalladas y uso de cada uno de estos métodos.


    1. to_numeric()

    La mejor manera de convertir una o más columnas de una DataFrame para los valores numéricos, es el uso de pandas.to_numeric().

    Esta función intentará cambiar no numéricos de los objetos (tales como cadenas) en números enteros o de punto flotante los números según corresponda.

    Uso básico

    La entrada a to_numeric() es una Serie o una sola columna de una DataFrame.

    >>> s = pd.Series(["8", 6, "7.5", 3, "0.9"]) # mixed string and numeric values
    >>> s
    0      8
    1      6
    2    7.5
    3      3
    4    0.9
    dtype: object
    
    >>> pd.to_numeric(s) # convert everything to float values
    0    8.0
    1    6.0
    2    7.5
    3    3.0
    4    0.9
    dtype: float64

    Como se puede ver, una nueva Serie se devuelve. Recuerde asignar este resultado a una variable o nombre de columna para continuar usándolo:

    # convert Series
    my_series = pd.to_numeric(my_series)
    
    # convert column "a" of a DataFrame
    df["a"] = pd.to_numeric(df["a"])

    También se puede utilizar para convertir varias columnas de un DataFrame a través de la apply() método:

    # 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 pueden ser convertidas, que es probablemente todo lo que usted necesita.

    Manejo de errores

    Pero lo que si algunos de los valores no pueden ser convertidos a un tipo numérico?

    to_numeric() también tiene un errors palabra clave argumento que le permite a la fuerza de los no-valores numéricos se NaN, o simplemente hacer caso omiso de las columnas que contienen estos valores.

    He aquí un ejemplo del uso de una Serie de cadenas de s que tiene el objeto dtype:

    >>> 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 por defecto es subir si no se puede convertir un valor. En este caso, no puede hacer frente con la cadena ‘pandas’:

    >>> pd.to_numeric(s) # or pd.to_numeric(s, errors='raise')
    ValueError: Unable to parse string

    Lugar de fallar, puede que quiera ‘pandas’ que se considera una falta o mala valor numérico. Nos puede obligar a valores no válidos para NaN como sigue utilizando el errors palabra clave argumento:

    >>> 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 un valor no válido se encuentra:

    >>> pd.to_numeric(s, errors='ignore')
    # the original Series is returned untouched

    Esta última opción es especialmente útil cuando se desea convertir toda tu DataFrame, pero no sé cual de nuestras columnas se pueden convertir de forma fiable a un tipo numérico. En ese caso, sólo escribir:

    df.apply(pd.to_numeric, errors='ignore')

    La función se aplicará a cada columna de la DataFrame. Las columnas que pueden ser convertidos a un tipo numérico se convierte, mientras que las columnas que no (por ejemplo, que no contienen cadenas de dígitos o fechas) se quedó solo.

    Downcasting

    Por defecto, la conversión con to_numeric() le dará un int64 o float64 dtype (o lo que sea entero ancho es nativo de la plataforma).

    Que es generalmente lo que quiere, pero lo que si se quería ahorrar algo de memoria y el uso de una versión más compacta dtype, como float32, o int8?

    to_numeric() le da la opción al abatido a ‘entero’, ‘firmado’, ‘unsigned’, ‘float’. He aquí un ejemplo de una simple serie s de tipo entero:

    >>> s = pd.Series([1, 2, -7])
    >>> s
    0    1
    1    2
    2   -7
    dtype: int64

    Downcasting ‘entero’ utiliza el mínimo número entero que puede contener los valores:

    >>> pd.to_numeric(s, downcast='integer')
    0    1
    1    2
    2   -7
    dtype: int8

    Downcasting ‘flotar’ del mismo modo escoge un menor de lo normal tipo flotante:

    >>> pd.to_numeric(s, downcast='float')
    0    1.0
    1    2.0
    2   -7.0
    dtype: float32

    2. astype()

    La astype() método permite ser explícito acerca de las dtype usted quiere que su DataFrame o Serie. Es muy versátil en el que usted puede probar y pasar de un tipo a la de cualquier otro.

    Uso básico

    Simplemente elegir un tipo: puede utilizar un NumPy dtype (por ejemplo,np.int16), algunos de Python tipos (por ejemplo, bool), o pandas-tipos específicos (como el de la categoría de los dtype).

    Llamar al método en el objeto que desea convertir y astype() va a tratar y convertir para 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')

    Aviso me dijo «probar» – si astype() no sabe cómo convertir un valor en la Serie o DataFrame, se producirá un error. Por ejemplo, si usted tiene un NaN o inf valor obtendrá un error de intentar convertir a un número entero.

    Como de los pandas 0.20.0, este error puede ser suprimida por el paso de errors='ignore'. Su objeto original serán devueltos intactos.

    Tener cuidado

    astype() es poderosa, pero a veces va a convertir valores «incorrectamente». Por ejemplo:

    >>> s = pd.Series([1, 2, -7])
    >>> s
    0    1
    1    2
    2   -7
    dtype: int64

    Estos son enteros pequeños, así que ¿cómo convertir a un entero de 8 bits tipo de guardar la memoria?

    >>> s.astype(np.uint8)
    0      1
    1      2
    2    249
    dtype: uint8

    La conversión funcionó, pero el -7 estaba envuelto ronda para convertirse en 249 (es decir, la 28 – 7)!

    Tratando abatido el uso de pd.to_numeric(s, downcast='unsigned') lugar podría ayudar a evitar este error.


    3. infer_objects()

    Versión 0.21.0 de pandas introdujo el método infer_objects() para la conversión de las columnas de un DataFrame que tiene un objeto tipo de datos de un modo más específico (tipo de conversiones aproximadas).

    Por ejemplo, he aquí un DataFrame con dos columnas de tipo de objeto. Uno sostiene real de los números enteros y la otra sostiene cadenas que representan los números enteros:

    >>> df = pd.DataFrame({'a': [7, 1, 5], 'b': ['3','2','1']}, dtype='object')
    >>> df.dtypes
    a    object
    b    object
    dtype: object

    Utilizando infer_objects(), usted puede cambiar el tipo de la columna ‘a’ int64:

    >>> df = df.infer_objects()
    >>> df.dtypes
    a     int64
    b    object
    dtype: object

    La columna ‘b’ ha sido dejado solo, ya que sus valores eran cadenas de caracteres, no enteros. Si quería intentar forzar la conversión de ambas columnas a un tipo entero, se podría utilizar df.astype(int) lugar.

    • También, a diferencia de .astype(float), este va a convertir cadenas a Nan en lugar de generar un error
    • .convert_objects es depracated desde 0.17 uso df.to_numeric lugar
    • Gracias – que debo actualizar esta respuesta. Es tal vez la pena señalar que pd.to_numeric y su compañero de métodos sólo funcionará en una columna a la vez, a diferencia de convert_objects. La discusión acerca de una función de reemplazo en la API parece ser curso; espero un método que funciona a través de todo el DataFrame seguirá siendo porque es muy útil.
    • ¿Cuál es la mejor manera de convertir todas las columnas que son en la actualidad, decir, int64 a int32?
    • probablemente la mejor manera de utilizar astype (como en la otra respuesta), es decir,.astype(numpy.int32).
    • Quiero decir ¿cómo aplicar la astype sólo a las columnas que están actualmente int64?
    • Es allí una manera de hacerlo en su lugar? Algo así como, df[var_name].astype("float", inplace = True)? Gracias

  2. 428

    ¿Qué hay de 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
    • Se puede hacer esto cuando el dataframe se crea?
    • Sí! pd.DataFrame tiene un dtype argumento de que podría dejar de hacer w/ usted está buscando. df = dp.DataFrame(a, columnas=[‘uno’, ‘dos’, ‘tres’], dtype=float) En [2]: df.dtypes Out[2]: un objeto de dos float64 tres float64 dtype: objeto
    • Cuando trato como se ha sugerido, me sale un aviso SettingWithCopyWarning: 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 haber sido introducido en la versión más reciente de los pandas y yo no veo nada malo como un resultado, pero me pregunto lo que esta advertencia es todo acerca de. Alguna idea?
    • la advertencia es para alertar a los usuarios la posibilidad de confundir el comportamiento con el encadenado de las operaciones, y con los pandas devolver copias de lugar de edición dataframes. consulte stackoverflow.com/questions/20625582/… y relacionados.
    • Eso es un buen método, pero no funciona cuando hay NaN en una columna. No tienen idea de por qué NaN no puede permanecer NaN cuando la conversión de float a int: ValueError: Cannot convert NA to integer
    • porque numpy enteros no tienen una representación para NaN: pandas.pydata.org/pandas-docs/stable/…
    • es posible pasar diferentes dtype‘s para diferentes columnas?
    • sí, en un diccionario. df = pd.DataFrame(a, columns=['one', 'two', 'three'], dtype={'one': str, 'two': int, 'three': float}). Estoy teniendo un tiempo difícil encontrar la especificación aceptada «dtype los valores de» a pesar de. Una lista que sería bueno (actualmente hago dict(enumerate(my_list))).
    • No puede funcionar .Se plantean ValueError: entry not a 2- or 3- tuple
    • Estoy en esto. Pregunta tonta, ¿por qué no funciona si lo haces df.loc de esta manera? Es b/c que devuelve una copia o algo?
    • ¿cómo se puede hacer esto con un multi-indexada dataframe?
    • Esto también convierte datetimes.

  3. 36

    esta a continuación el código va a cambiar el tipo de datos de columna.

    df[['col.name1', 'col.name2'...]] = df[['col.name1', 'col.name2'..]].astype('data_type')

    en lugar del tipo de datos que usted puede dar a su tipo de datos .¿qué quieres como str,float,int, etc.

    • Cuenta que cuando la aplicación esta en una columna que contiene las cadenas « ‘Verdadero’ « y « ‘False’ « mediante el data_type bool, todo ha cambiado para True.
    • Esta opción también se puede convertir al tipo de «categoría»
  4. 15

    Aquí es una función que toma como argumentos un DataFrame y una lista de columnas y coacciona a todos los datos en las columnas de 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')

    Así, por 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'])
    • lo que si se desea utilizar índices de las columnas en lugar de los nombres de columna?
  5. 7

    Cuando sólo he necesarios para especificar las columnas, y quiero ser explícito, yo he usado (por DOCS UBICACIÓN):

    dataframe = dataframe.astype({'col_name_1':'int','col_name_2':'float64', etc. ...})

    Así, el uso de la pregunta original, sino que proporciona los nombres de columna se …

    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'})
  6. 6

    Cómo acerca de la creación de dos dataframes, cada uno con diferentes tipos de datos para las columnas y, a continuación, anexando 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 que el dataframe es creado, usted puede rellenar con variables de punto flotante en la 1ª columna, y las cadenas (o cualquier tipo de datos que usted desea) en la 2ª columna.

  7. 1

    Pensé que tenía el mismo problema pero en realidad tengo una ligera diferencia que hace el problema más fácil de resolver. Para los demás mirando a esta pregunta es vale la pena comprobar el formato de la lista de entrada. En mi caso los números son inicialmente flota no cadenas como en la pregunta:

    a = [['a', 1.2, 4.2], ['b', 70, 0.03], ['x', 5, 0]]

    pero por el procesamiento de la lista mucho antes de la creación del dataframe pierdo los tipos y todo se convierte en una cadena.

    La creación de la trama de datos a través de una colección de la matriz de

    df = pd.DataFrame(np.array(a))
    
    df
    Out[5]: 
       0    1     2
    0  a  1.2   4.2
    1  b   70  0.03
    2  x    5     0
    
    df[1].dtype
    Out[7]: dtype('O')

    da el mismo marco de datos como en la pregunta, donde las entradas en las columnas 1 y 2 son considerados como cadenas. Sin embargo, si

    df = pd.DataFrame(a)
    
    df
    Out[10]: 
       0     1     2
    0  a   1.2  4.20
    1  b  70.0  0.03
    2  x   5.0  0.00
    
    df[1].dtype
    Out[11]: dtype('float64')

    ¿ realmente dar un marco de datos con las columnas en el formato correcto

Dejar respuesta

Please enter your comment!
Please enter your name here