python / pandas: convierte el mes int al nombre del mes

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: