La mayor parte de la información que encontré no estaba en python> pandas> dataframe por lo tanto, la pregunta.
Quiero transformar un número entero entre 1 y 12 en un nombre de mes abreviado.
Tengo un df que se parece a
client Month 1 sss 02 2 yyy 12 3 www 06
Quiero que la df se vea así:
client Month 1 sss Feb 2 yyy Dec 3 www Jun
Puede hacerlo de manera eficiente combinando calendar.month_abbr
y df[col].apply()
import calendar df['Month'] = df['Month'].apply(lambda x: calendar.month_abbr[x])
Una forma de hacerlo es con el método de apply
en el dataframe pero, para hacerlo, necesita un mapa para convertir los meses. Puede hacerlo con una función / diccionario o con la propia fecha y hora de Python.
Con la fecha y hora sería algo como:
def mapper(month): date = datetime.datetime(2000, month, 1) # You need a dateobject with the proper month return date.strftime('%b') # %b returns the months abbreviation, other options [here][1] df['Month'].apply(mapper)
De manera similar, puede crear su propio mapa para nombres personalizados. Se vería así:
months_map = {01: 'Jan', 02: 'Feb'} def mapper(month): return months_map[month]
Obviamente, no necesita definir estas funciones explícitamente y podría usar un lambda
directamente en el método de aplicación.
Puede hacerlo fácilmente con una columna de aplicar.
import pandas as pd df = pd.DataFrame({'client':['sss', 'yyy', 'www'], 'Month': ['02', '12', '06']}) look_up = {'01': 'Jan', '02': 'Feb', '03': 'Mar', '04': 'Apr', '05': 'May', '06': 'Jun', '07': 'Jul', '08': 'Aug', '09': 'Sep', '10': 'Oct', '11': 'Nov', '12': 'Dec'} df['Month'] = df['Month'].apply(lambda x: look_up[x]) df Month client 0 Feb sss 1 Dec yyy 2 Jun www
Utilice la función strptime
y lambda
para esto:
from time import strptime df['Month'] = df['Month'].apply(lambda x: strptime(x,'%b').tm_mon)
Como los nombres de los meses abreviados son las primeras tres letras de sus nombres completos, primero podemos convertir la columna Month
a datetime
y luego usar dt.month_name()
para obtener el nombre del mes completo y finalmente usar el método str.slice()
para obtener el Las tres primeras letras, todas con pandas y solo en una línea de código:
df['Month'] = pd.to_datetime(df['Month'], format='%m').dt.month_name().str.slice(stop=3) df Month client 0 Feb sss 1 Dec yyy 2 Jun www
Habiendo probado todo esto en un conjunto de datos grande, he encontrado que lo siguiente es más rápido:
import calendar def month_mapping(): # I'm lazy so I have a stash of functions already written so # I don't have to write them out every time. This returns the # {1:'Jan'....12:'Dec'} dict in the laziest way... abbrevs = {} for month in range (1, 13): abbrevs[month] = calendar.month_abbr[month] return abbrevs abbrevs = month_mapping() df['Month Abbrev'} = df['Date Col'].dt.month.map(mapping)
El módulo de calendar
es útil, pero calendar.month_abbr
es similar a una matriz: no se puede usar directamente de forma vectorializada. Para una asignación eficiente, puede construir un diccionario y luego usar pd.Series.map
:
import calendar d = dict(enumerate(calendar.month_abbr)) df['Month'] = df['Month'].map(d)
La evaluación comparativa del rendimiento muestra un diferencial de rendimiento de ~ 130x:
import calendar d = dict(enumerate(calendar.month_abbr)) mapper = calendar.month_abbr.__getitem__ np.random.seed(0) n = 10**5 df = pd.DataFrame({'A': np.random.randint(1, 13, n)}) %timeit df['A'].map(d) # 7.29 ms per loop %timeit df['A'].map(mapper) # 946 ms per loop
def mapper(month): return month.strftime('%b') df['Month'] = df['Month'].apply(mapper)
Referencia: