convertir todo el marco de datos de pandas a enteros en pandas (0.17.0)

6 minutos de lectura

Avatar de usuario de Bobe Kryant
Bobe Kryant

Mi pregunta es muy similar a esta, pero necesito convertir mi marco de datos completo en lugar de solo una serie. El to_numeric La función solo funciona en una serie a la vez y no es un buen reemplazo para el obsoleto convert_objects dominio. ¿Hay alguna manera de obtener resultados similares a los convert_objects(convert_numeric=True) comando en la nueva versión de pandas?

Gracias Mike Müller por tu ejemplo. df.apply(pd.to_numeric) funciona muy bien si todos los valores se pueden convertir a números enteros. ¿Qué sucede si en mi marco de datos tengo cadenas que no se pueden convertir en números enteros? Ejemplo:

df = pd.DataFrame({'ints': ['3', '5'], 'Words': ['Kobe', 'Bryant']})
df.dtypes
Out[59]: 
Words    object
ints     object
dtype: object

Entonces podría ejecutar la función obsoleta y obtener:

df = df.convert_objects(convert_numeric=True)
df.dtypes
Out[60]: 
Words    object
ints      int64
dtype: object

ejecutando el apply El comando me da errores, incluso con el manejo de prueba y excepción.

Avatar de usuario de Mike Müller
mike muller

Todas las columnas convertibles

Puede aplicar la función a todas las columnas:

df.apply(pd.to_numeric)

Ejemplo:

>>> df = pd.DataFrame({'a': ['1', '2'], 
                       'b': ['45.8', '73.9'],
                       'c': [10.5, 3.7]})

>>> df.info()
<class 'pandas.core.frame.DataFrame'>
Int64Index: 2 entries, 0 to 1
Data columns (total 3 columns):
a    2 non-null object
b    2 non-null object
c    2 non-null float64
dtypes: float64(1), object(2)
memory usage: 64.0+ bytes

>>> df.apply(pd.to_numeric).info()
<class 'pandas.core.frame.DataFrame'>
Int64Index: 2 entries, 0 to 1
Data columns (total 3 columns):
a    2 non-null int64
b    2 non-null float64
c    2 non-null float64
dtypes: float64(2), int64(1)
memory usage: 64.0 bytes

No todas las columnas convertibles

pd.to_numeric tiene el argumento de palabra clave errors:

  Signature: pd.to_numeric(arg, errors="raise")
  Docstring:
  Convert argument to a numeric type.

Parameters
----------
arg : list, tuple or array of objects, or Series
errors : {'ignore', 'raise', 'coerce'}, default 'raise'
    - If 'raise', then invalid parsing will raise an exception
    - If 'coerce', then invalid parsing will be set as NaN
    - If 'ignore', then invalid parsing will return the input

Configurándolo en ignore devolverá la columna sin cambios si no se puede convertir a un tipo numérico.

Como señaló Anton Protopopov, la forma más elegante es suministrar ignore como argumento de palabra clave para apply():

>>> df = pd.DataFrame({'ints': ['3', '5'], 'Words': ['Kobe', 'Bryant']})
>>> df.apply(pd.to_numeric, errors="ignore").info()
<class 'pandas.core.frame.DataFrame'>
Int64Index: 2 entries, 0 to 1
Data columns (total 2 columns):
Words    2 non-null object
ints     2 non-null int64
dtypes: int64(1), object(1)
memory usage: 48.0+ bytes

Mi forma sugerida anteriormente, usando parcial del módulo functoolses más detallado:

>>> from functools import partial
>>> df = pd.DataFrame({'ints': ['3', '5'], 
                       'Words': ['Kobe', 'Bryant']})
>>> df.apply(partial(pd.to_numeric, errors="ignore")).info()
<class 'pandas.core.frame.DataFrame'>
Int64Index: 2 entries, 0 to 1
Data columns (total 2 columns):
Words    2 non-null object
ints     2 non-null int64
dtypes: int64(1), object(1)
memory usage: 48.0+ bytes

  • Creo que la forma más elegante de establecer este argumento en el apply como clave: df.apply(pd.to_numeric, errors='ignore') debería funcionar bien

    – Antón Protopopov

    18 de enero de 2016 a las 5:58

  • to_numeric no hace comas.

    – ChaimG

    8 de junio de 2020 a las 15:25

  • Para obtener solo columnas numéricas enteras al final, como indica la pregunta, recorra todas las columnas: for i in df.columns: try: df[[i]] = df[[i]].astype(int) except: pass

    – pregunta a42

    30 de noviembre de 2020 a las 23:02


avatar de usuario de questionto42
pregunta a42

La respuesta aceptada con pd.to_numeric() se convierte en flotante, tan pronto como se necesita. Leyendo la pregunta en detalle, se trata de convertir cualquier columna numérica a entero. Es por eso que la respuesta aceptada necesita un bucle sobre todas las columnas para convertir los números a int al final.

Solo para completar, esto es incluso posible sin pd.to_numeric(); por supuesto, esto no es recomendable:

df = pd.DataFrame({'a': ['1', '2'], 
                   'b': ['45.8', '73.9'],
                   'c': [10.5, 3.7]})

for i in df.columns:
    try:
        df[[i]] = df[[i]].astype(float).astype(int)
    except:
        pass

print(df.dtypes)

Afuera:

a    int32
b    int32
c    int32
dtype: object

EDITADO:
Tenga en cuenta que esta solución no recomendada es innecesariamente complicada; pd.to_numeric() simplemente puede usar el argumento de palabra clave downcast="integer" para forzar enteros como salida, gracias por el comentario. Sin embargo, esto todavía falta en la respuesta aceptada.

Noticias de nuevo
De un comentario del usuario Gary, resulta que “a partir de pandas 2.0.1, si la serie de entrada contiene una cadena vacía o None entonces el dtype resultante seguirá siendo flotante incluso cuando se use downcast="integer"“. Eso significaría que la primera respuesta con .astype(float).astype(int) está vivo de nuevo si quiere asegurarse de obtener solo números enteros.

  • Si todos los ‘números’ están formateados como enteros (es decir, '5'no '5.0') entonces el argumento de la palabra clave downcast='integer' se puede utilizar en el to_numeric función para forzar el tipo entero: En este ejemplo df.apply(pd.to_numeric, downcast='integer') devolverá la columna a como entero

    – JJL

    29 de diciembre de 2020 a las 22:22


  • Tenga en cuenta que a partir de pandas 2.0.1, si la serie de entrada contiene una cadena vacía o None entonces el dtype resultante seguirá siendo flotante incluso cuando se use downcast='integer'.

    – Gary

    18 de mayo a las 18:44

puede usar df.astype() para convertir la serie al tipo de datos deseado.

Por ejemplo: my_str_df = [[’20’,’30’,’40’]]

entonces: my_int_df = my_str_df[‘column_name’].astype(int) # este será el tipo int

  • Voto negativo. La pregunta era sobre un marco de datos, no una serie, y no explica cómo cambiaría un marco de datos completo que también tiene columnas flotantes de tipo cadena como ‘45.8’.

    – pregunta a42

    30 de noviembre de 2020 a las 22:48

apply() el pd.to_numeric con errors="ignore" y asignarlo de nuevo al DataFrame:

df = pd.DataFrame({'ints': ['3', '5'], 'Words': ['Kobe', 'Bryant']})
print ("Orig: \n",df.dtypes)

df.apply(pd.to_numeric, errors="ignore")
print ("\nto_numeric: \n",df.dtypes)

df = df.apply(pd.to_numeric, errors="ignore")
print ("\nto_numeric with assign: \n",df.dtypes)

Producción:

Orig: 
 ints     object
Words    object
dtype: object

to_numeric: 
 ints     object
Words    object
dtype: object

to_numeric with assign: 
 ints      int64
Words    object
dtype: object

¿Ha sido útil esta solución?