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.
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 functools
es 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
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 clavedowncast='integer'
se puede utilizar en elto_numeric
función para forzar el tipo entero: En este ejemplodf.apply(pd.to_numeric, downcast='integer')
devolverá la columnaa
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 usedowncast='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