Asegurar datos numéricos#

Como vimos en la sección dedicada a tipos de datos en pandas, los tipos de datos con los que podremos realizar operaciones son int64 y float64. También vimos que en la mayoría de ocasiones, estos tipos pueden estar expresados en forma de tipo object. Incluso, algunos de estos datos están en forma de string.

Nota

Para este apartado usaré datos de ejemplo porque nuestros conjuntos de datos muestra_covid y geolocalizacion no necesitan una transformación adicional.

Revisa tu conjunto de datos para saber si esta es una operación necesaria o no.

Al igual que en las operaciones anteriores, pandas incluye una función que permite convertir los datos a un tipo numérico.

import pandas as pd
s = pd.Series(["1", "2", "3", "4", "5"])
print(s.dtypes)
pd.to_numeric(s)
object
0    1
1    2
2    3
3    4
4    5
dtype: int64

Notarás que cuando llamamos a la función to_numeric, los datos se convierten a tipo int64 y de la misma manera lo puede hacer con cualquier columna que contenga datos numéricos. Sin embargo, no puede hacerlo con todo el dataframe al mismo tiempo, por ejemplo:

df = pd.DataFrame({"A": ["Camila", "Sebastián", "Santiago", "Jimena", "Hannah"], "B": ["1.5", "1.2", "2.3", "4.5", "5.6"], "C": ["1", "2", "3", "4", "5"]})
print(df.dtypes)
pd.to_numeric(df)
A    object
B    object
C    object
dtype: object
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
/var/folders/6z/cjmzygfj49d6yzn_qgny7hgr0000gp/T/ipykernel_99193/1763755439.py in <module>
      1 df = pd.DataFrame({"A": ["Camila", "Sebastián", "Santiago", "Jimena", "Hannah"], "B": ["1.5", "1.2", "2.3", "4.5", "5.6"], "C": ["1", "2", "3", "4", "5"]})
      2 print(df.dtypes)
----> 3 pd.to_numeric(df)

~/opt/anaconda3/lib/python3.9/site-packages/pandas/core/tools/numeric.py in to_numeric(arg, errors, downcast)
    161         values = np.array([arg], dtype="O")
    162     elif getattr(arg, "ndim", 1) > 1:
--> 163         raise TypeError("arg must be a list, tuple, 1-d array, or Series")
    164     else:
    165         values = arg

TypeError: arg must be a list, tuple, 1-d array, or Series

Lo anterior nos arroja un TypeError porque pandas estaba esperando una Serie, es decir, el conjunto de datos de una sola columna.

Para transformar estos datos podemos utilizar el método tradicional de for loop así:

for col in df.columns:
  try:
    df[col] = pd.to_numeric(df[col])
  except ValueError:
    pass

df.dtypes
A     object
B    float64
C      int64
dtype: object

El problema con este método es que es un poco lento. De hecho, en un conjunto de datos como covid_nacional tomaría muchos minutos y gastaría mucha memoria, tanto que podría simplemente bloquear la computadora.

En términos de eficiencia es mejor utilizar el método de pandas apply(). Veremos un poco más sobre el uso de este método en la sección dedicada a apply(), pero por lo pronto veremos un ejemplo de como usarlo.

df = pd.DataFrame({"A": ["Camila", "Sebastián", "Santiago", "Jimena", "Hannah"], "B": ["1.5", "1.2", "2.3", "4.5", "5.6"], "C": ["1", "2", "3", "4", "5"]})
cols = df.columns.drop('A') # Eliminamos la columna que sabemos tiene valores de texto
df[cols] = df[cols].apply(pd.to_numeric)
df.dtypes
A     object
B    float64
C      int64
dtype: object

Observación

La conversión de datos numéricos, así como la de fechas, que veremos a continuación, es una operación que se realiza sobre una sola columna. Por esa razón es importante que hayas realizado previamente la identificación de tipos de datos.