Saltar al contenido

¿Cómo mapear datos en una serie de Pandas?

…para obtener nuevas series de datos derivadas de una serie original.

Muchas veces, cuando usamos pandas, tenemos una serie de datos a la que le aplicamos una transformación. En muchos casos, esa transformación puede ser aplicarle una función. Por ejemplo, tengo una serie de datos de temperatura en grados Farenheit y la quiero transformar a grados Celsius. Podría aplicar algo como lo siguiente:

import numpy as np
import pandas as pd

df = pd.DataFrame({'T_Farenheit': range(100)})
df['T_Celsius'] = df.loc[:, 'T_Farenheit'].map(lambda t: (t - 32) * 5 / 9)
print(df)

El anterior DataFrame se vería así:

    T_Farenheit  T_Celsius
0             0 -17.777778
1             1 -17.222222
2             2 -16.666667
3             3 -16.111111
4             4 -15.555556
..          ...        ...
95           95  35.000000
96           96  35.555556
97           97  36.111111
98           98  36.666667
99           99  37.222222

[100 rows x 2 columns]

Esto está muy bien pero no siempre es lo que necesitamos porque no siempre tenemos una función que defina la transformación que necesitamos hacer de forma sencilla. Por ejemplo, podemos hacer un experimento del cual derivamos una Look-up table que nos permite transformar valores o podemos obtener esta Look-up Table de un artículo.

Como alternativa podemos usar un diccionario que haga un mapeo de los valores de la serie original a la serie que deseeamos obtener.

Un ejemplo (sin mucho sentido) de esto podría ser:

mapeo  = {i: np.random.rand() for i in range(100)}
df['T_exp'] = df.loc[:, 'T_Farenheit'].map(mapeo)

print(df)

Y el anterior DataFrame se vería ahora así:

    T_Farenheit  T_Celsius     T_exp
0             0 -17.777778  0.687012
1             1 -17.222222  0.128531
2             2 -16.666667  0.324474
3             3 -16.111111  0.022591
4             4 -15.555556  0.889970
..          ...        ...       ...
95           95  35.000000  0.449293
96           96  35.555556  0.054644
97           97  36.111111  0.928684
98           98  36.666667  0.289097
99           99  37.222222  0.450386

[100 rows x 3 columns]

¿Qué pasaría si parte de los datos no estuvieran definidos en la transformación, estuvieran fuera de rango,etc? pandas nos lo pone fácil ya que nos permite usar un diccionario que defina un método __missing__ (nuestra propia subclase de un diccionario). Por ejemplo, imaginemos que no tenemos valores definidos para los valores de partida superiores a 50? o que a partir de ese valor deberíamos considerarlos como constantes. Lo podríamos hacer así de la siguiente forma donde los valores por encima de 50? les doy un valor de -999 y a los que están por debajo les damos un valor aleatorio (valor sin sentido):

class MyDict(dict):
    def __missing__(self, key):
        return -999

mapeo = MyDict({i: np.random.randn() for i in range(51)})
df['T_map'] = df.loc[:, 'T_Farenheit'].map(mapeo)

print(df)

Y el resultado del anterior DataFrame se vería:

    T_Farenheit  T_Celsius     T_exp       T_map
0             0 -17.777778  0.687012    0.510506
1             1 -17.222222  0.128531   -0.299574
2             2 -16.666667  0.324474    1.181474
3             3 -16.111111  0.022591    0.506276
4             4 -15.555556  0.889970    0.299538
..          ...        ...       ...         ...
95           95  35.000000  0.449293 -999.000000
96           96  35.555556  0.054644 -999.000000
97           97  36.111111  0.928684 -999.000000
98           98  36.666667  0.289097 -999.000000
99           99  37.222222  0.450386 -999.000000

[100 rows x 4 columns]

Y eso es todo, un artículo sencillo sobre una funcionalidad de pandas que no es nueva. El otro día me hizo falta y me he decidido a escribir sobre ello.

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

fifty two − = forty seven

Pybonacci