¿Convertir flotadores a int en pandas?

230

He estado trabajando con datos importados de un CSV. Los pandas cambiaron algunas columnas para flotar, por lo que ahora los números en estas columnas se muestran como puntos flotantes. Sin embargo, necesito que se muestren como enteros o sin coma. ¿Hay alguna manera de convertirlos a enteros o no mostrar la coma?

MJP
fuente
22
Puede cambiar el tipo (siempre que no falten valores)df.col = df.col.astype(int)
EdChum
Esta pregunta es dos preguntas al mismo tiempo, y el título de esta pregunta refleja solo una de ellas.
Monica Heddneck
Para una gente que cumple con lo anterior y lo encuentra útil en concepto pero no funciona para usted, esta es la versión que funcionó para mí en Python 3.7.5 con pandas X:df = df.astype(int)
Oliver.R

Respuestas:

217

Para modificar la salida flotante, haga esto:

df= pd.DataFrame(range(5), columns=['a'])
df.a = df.a.astype(float)
df

Out[33]:

          a
0 0.0000000
1 1.0000000
2 2.0000000
3 3.0000000
4 4.0000000

pd.options.display.float_format = '{:,.0f}'.format
df

Out[35]:

   a
0  0
1  1
2  2
3  3
4  4
EdChum
fuente
16
¡Gracias! Ajusté esto en mi to_csv: fin.to_csv ('my_table.csv', float_format = '%. F'). ¡Funcionó!
MJP
44
En la última versión de pandas, debe agregar copy = False a los argumentos de astype para evitar una advertencia
g.stevo
¿Es necesario hacer df.a = df.a.astype(float)? ¿Esto hace una copia (no estoy seguro de cómo se usa el copyparámetro astype())? De todos modos para actualizar el tipo "en el lugar"?
Mr_and_Mrs_D
1
@EdChum, ¿hay alguna manera de evitar que Pandas convierta tipos para empezar? Por ejemplo, pruebe DF.({'200': {'#': 354, '%': 0.9971830985915493}, '302': {'#': 1, '%': 0.0028169014084507044}}) Tenga en cuenta que # se convierte en flotante y son filas, no columnas. porque cada uno es un Seriesque solo puede almacenar un solo tipo de uniforme?
alancalvitti
@alancalvitti, ¿cuál es su intención aquí para preservar los valores o el dtype? Si es dtypeentonces usted necesita para crear estas columnas dtype objectpor lo que permite mixta, de lo contrario mi consejo sería utilizar simplemente flotar y cuando las comparaciones que hacen usonp.isclose
EdChum
180

Use la pandas.DataFrame.astype(<type>)función para manipular los tipos de columna.

>>> df = pd.DataFrame(np.random.rand(3,4), columns=list("ABCD"))
>>> df
          A         B         C         D
0  0.542447  0.949988  0.669239  0.879887
1  0.068542  0.757775  0.891903  0.384542
2  0.021274  0.587504  0.180426  0.574300
>>> df[list("ABCD")] = df[list("ABCD")].astype(int)
>>> df
   A  B  C  D
0  0  0  0  0
1  0  0  0  0
2  0  0  0  0

EDITAR:

Para manejar valores perdidos:

>>> df
          A         B     C         D
0  0.475103  0.355453  0.66  0.869336
1  0.260395  0.200287   NaN  0.617024
2  0.517692  0.735613  0.18  0.657106
>>> df[list("ABCD")] = df[list("ABCD")].fillna(0.0).astype(int)
>>> df
   A  B  C  D
0  0  0  0  0
1  0  0  0  0
2  0  0  0  0
Ryan G
fuente
3
Probé su enfoque y me da un ValueError: no se puede convertir NA a entero
MJP
66
@MJP No puede convertir series de flotante a entero si faltan valores, vea pandas.pydata.org/pandas-docs/stable/… , debe usar flotantes
EdChum
2
No faltan los valores, pero la columna no especifica un valor para cada fila a propósito. ¿Hay alguna forma de lograr una solución? Como esos valores son identificadores de clave externa, necesito ints.
MJP
44
Hice una edición en la que todos los NaN se reemplazan con un 0.0.
Ryan G
3
O mejor aún, si solo está modificando un CSV, entonces: df.to_csv ("path.csv", na_rep = "", float_format = "%. 0f", index = False) Pero esto editará todos los flotantes, así que puede ser mejor convertir su columna FK en una cadena, hacer la manipulación y luego guardarla.
Ryan G
44

Teniendo en cuenta el siguiente marco de datos:

>>> df = pd.DataFrame(10*np.random.rand(3, 4), columns=list("ABCD"))
>>> print(df)
...           A         B         C         D
... 0  8.362940  0.354027  1.916283  6.226750
... 1  1.988232  9.003545  9.277504  8.522808
... 2  1.141432  4.935593  2.700118  7.739108

Usando una lista de nombres de columna, cambie el tipo de varias columnas con applymap():

>>> cols = ['A', 'B']
>>> df[cols] = df[cols].applymap(np.int64)
>>> print(df)
...    A  B         C         D
... 0  8  0  1.916283  6.226750
... 1  1  9  9.277504  8.522808
... 2  1  4  2.700118  7.739108

O para una sola columna con apply():

>>> df['C'] = df['C'].apply(np.int64)
>>> print(df)
...    A  B  C         D
... 0  8  0  1  6.226750
... 1  1  9  9  8.522808
... 2  1  4  2  7.739108
Jaroslav Bezděk
fuente
55
¿Qué pasa si hay un NaN en el valor?
Zhang18
3
@ Zhang18 Probé esta solución y en caso de NaN tiene este error:ValueError: ('cannot convert float NaN to integer', u'occurred at index <column_name>')
enri
2
@enri: puede probar el siguiente códigodf['C'] = df['C'].dropna().apply(np.int64)
vsdaking
12

Esta es una solución rápida en caso de que desee convertir más columnas de su pandas.DataFrameflotante a entero considerando también el caso de que pueda tener valores de NaN.

cols = ['col_1', 'col_2', 'col_3', 'col_4']
for col in cols:
   df[col] = df[col].apply(lambda x: int(x) if x == x else "")

Intenté con else x)y else None), pero el resultado sigue teniendo el número flotante, así que lo usé else "".

enri
fuente
se aplicará ""a todos los valores encol
Raheel
Aplicará una cadena vacía ("") a todos los valores faltantes, si eso es lo que se requiere, pero el resto de los valores serán enteros.
Krzysztof Słowiński
Gracias por esto. Esto funcionó cuando .astype () y .apply (np.int64) no funcionaron.
Alison S
Esto se siente raro, y no veo ninguna razón para usarlo en las muchas alternativas disponibles.
AMC
8

Ampliando el uso mencionado del pandas.DataFrame.astype(<type>)método @Ryan G , se puede usar el errors=ignoreargumento para convertir solo aquellas columnas que no producen un error, lo que simplifica notablemente la sintaxis. Obviamente, se debe tener precaución al ignorar los errores, pero para esta tarea resulta muy útil.

>>> df = pd.DataFrame(np.random.rand(3, 4), columns=list('ABCD'))
>>> df *= 10
>>> print(df)
...           A       B       C       D
... 0   2.16861 8.34139 1.83434 6.91706
... 1   5.85938 9.71712 5.53371 4.26542
... 2   0.50112 4.06725 1.99795 4.75698

>>> df['E'] = list('XYZ')
>>> df.astype(int, errors='ignore')
>>> print(df)
...     A   B   C   D   E
... 0   2   8   1   6   X
... 1   5   9   5   4   Y
... 2   0   4   1   4   Z

De pandas.DataFrame.astype docs:

errores: {'raise', 'ignore'}, predeterminado 'raise'

Controle el aumento de excepciones en datos no válidos para el tipo proporcionado.

  • raise: permitir que se generen excepciones
  • ignorar: suprimir excepciones. En caso de error, devuelva el objeto original

Nuevo en la versión 0.20.0.

aebmad
fuente
7
>>> import pandas as pd
>>> right = pd.DataFrame({'C': [1.002, 2.003], 'D': [1.009, 4.55], 'key': ['K0', 'K1']})
>>> print(right)
           C      D key
    0  1.002  1.009  K0
    1  2.003  4.550  K1
>>> right['C'] = right.C.astype(int)
>>> print(right)
       C      D key
    0  1  1.009  K0
    1  2  4.550  K1
usuario8051244
fuente
5

Para convertir todas las columnas flotantes a int

>>> df = pd.DataFrame(np.random.rand(5, 4) * 10, columns=list('PQRS'))
>>> print(df)
...     P           Q           R           S
... 0   4.395994    0.844292    8.543430    1.933934
... 1   0.311974    9.519054    6.171577    3.859993
... 2   2.056797    0.836150    5.270513    3.224497
... 3   3.919300    8.562298    6.852941    1.415992
... 4   9.958550    9.013425    8.703142    3.588733

>>> float_col = df.select_dtypes(include=['float64']) # This will select float columns only
>>> # list(float_col.columns.values)
>>> for col in float_col.columns.values:
...     df[col] = df[col].astype('int64')
>>> print(df)
...     P   Q   R   S
... 0   4   0   8   1
... 1   0   9   6   3
... 2   2   0   5   3
... 3   3   8   6   1
... 4   9   9   8   3
Suhas_Pote
fuente
0

Aquí hay una función simple que convertirá los flotantes en el tipo entero más pequeño posible que no pierda ninguna información. Por ejemplo,

  • 100.0 se puede convertir de flotante a entero, pero 99.9 no (sin perder información por redondeo o truncamiento)

  • Además, 1.0 se puede int8bajar sin perder información, pero el tipo entero más pequeño para 100_000.0 esint32

Ejemplos de código:

import numpy as np
import pandas as pd

def float_to_int( s ):
    if ( s.astype(np.int64) == s ).all():
        return pd.to_numeric( s, downcast='integer' )
    else:
        return s

# small integers are downcast into 8-bit integers
float_to_int( np.array([1.0,2.0]) )
Out[1]:array([1, 2], dtype=int8)

# larger integers are downcast into larger integer types
float_to_int( np.array([100_000.,200_000.]) )
Out[2]: array([100000, 200000], dtype=int32)

# if there are values to the right of the decimal
# point, no conversion is made
float_to_int( np.array([1.1,2.2]) )
Out[3]: array([ 1.1,  2.2])
JohnE
fuente
0

Las columnas que deben convertirse a int se pueden mencionar en un diccionario también como a continuación

df = df.astype({'col1': 'int', 'col2': 'int', 'col3': 'int'})
prashanth
fuente
-5
>>> df_18['cyl'].value_counts()
... 4.0     365
... 6.0     246
... 8.0     153

>>> df_18['cyl'] = df_18['cyl'].astype(int)
>>> df_18['cyl'].value_counts()
... 4     365
... 6     246
... 8     153
RAHUL KUMAR
fuente
1
astype(int)Ya fue mencionado varias veces. Esta respuesta no agrega nada nuevo.
Georgy