Convert month int to month name in Pandas

Question:

I want to transform an integer between 1 and 12 into an abbrieviated month name.

I have a df which looks like:

   client Month
1  sss    02
2  yyy    12
3  www    06

I want the df to look like this:

   client Month
1  sss    Feb
2  yyy    Dec
3  www    Jun

Most of the info I found was not in python>pandas>dataframe hence the question.

Asked By: Boosted_d16

||

Answers:

You can do this easily with a column apply.

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
Answered By: andrew

One way of doing that is with the apply method in the dataframe but, to do that, you need a map to convert the months. You could either do that with a function / dictionary or with Python’s own datetime.

With the datetime it would be something like:

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)

In a simillar way, you could build your own map for custom names. It would look like this:

months_map = {01: 'Jan', 02: 'Feb'}
def mapper(month):
    return months_map[month]

Obviously, you don’t need to define this functions explicitly and could use a lambda directly in the apply method.

Answered By: pekapa

You can do this efficiently with combining calendar.month_abbr and df[col].apply()

import calendar
df['Month'] = df['Month'].apply(lambda x: calendar.month_abbr[x])
Answered By: EoinS

Use strptime and lambda function for this:

from time import strptime
df['Month'] = df['Month'].apply(lambda x: strptime(x,'%b').tm_mon) 
Answered By: Vagee

Having tested all of these on a large dataset, I have found the following to be fastest:

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)
Answered By: Heather

Since the abbreviated month names is the first three letters of their full names, we could first convert the Month column to datetime and then use dt.month_name() to get the full month name and finally use str.slice() method to get the first three letters, all using pandas and only in one line of code:

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
Answered By: today

The calendar module is useful, but calendar.month_abbr is array-like: it cannot be used directly in a vectorised fashion. For an efficient mapping, you can construct a dictionary and then use pd.Series.map:

import calendar
d = dict(enumerate(calendar.month_abbr))
df['Month'] = df['Month'].map(d)

Performance benchmarking shows a ~130x performance differential:

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
Answered By: jpp

Solution 1: One liner

df['Month'] = pd.to_datetime(df['Month'], format='%m').dt.strftime('%b')

Solution 2: Using apply()

def mapper(month):
   return month.strftime('%b') 

df['Month'] = df['Month'].apply(mapper)

Reference:

Answered By: Suhas_Pote

You can use Pandas month_name() function. Example:

>>> idx = pd.date_range(start='2018-01', freq='M', periods=3)
>>> idx
DatetimeIndex(['2018-01-31', '2018-02-28', '2018-03-31'],
                  dtype='datetime64[ns]', freq='M')
>>> idx.month_name()
Index(['January', 'February', 'March'], dtype='object')

For more detail visit this link.

Answered By: Nurul Akter Towhid

Suppose we have a DF like this, and Date is already in DateTime Format:

df.head(3)


            value   
date        
2016-05-19  19736   
2016-05-26  18060   
2016-05-27  19997   

Then we can extract month number and month name easily like this :

df['month_num'] = df.index.month
df['month'] = df.index.month_name()


            value   year    month_num  month
date                
2017-01-06  37353   2017    1          January
2019-01-06  94108   2019    1          January
2019-01-05  77897   2019    1          January
2019-01-04  94514   2019    1          January
Answered By: Abhishek Sengupta

using datetime object methods

I’m surpised this answer doesn’t have a solution using strftime

note, you’ll need to have a valid datetime object before using the strftime method, use pd.to_datetime(df['date_column']) to cast your target column to a datetime object.

import pandas as pd 

dates = pd.date_range('01-Jan 2020','01-Jan 2021',freq='M')

df = pd.DataFrame({'dates' : dates})
df['month_name'] = df['dates'].dt.strftime('%b')

   dates month_name
0  2020-01-31        Jan
1  2020-02-29        Feb
2  2020-03-31        Mar
3  2020-04-30        Apr
4  2020-05-31        May
5  2020-06-30        Jun
6  2020-07-31        Jul
7  2020-08-31        Aug
8  2020-09-30        Sep
9  2020-10-31        Oct
10 2020-11-30        Nov
11 2020-12-31        Dec

another method would be to slice the name using dt.month_name()

df['month_name_str_slice'] = df['dates'].dt.month_name().str[:3]

        dates month_name month_name_str_slice
0  2020-01-31        Jan                  Jan
1  2020-02-29        Feb                  Feb
2  2020-03-31        Mar                  Mar
3  2020-04-30        Apr                  Apr
4  2020-05-31        May                  May
5  2020-06-30        Jun                  Jun
6  2020-07-31        Jul                  Jul
7  2020-08-31        Aug                  Aug
8  2020-09-30        Sep                  Sep
9  2020-10-31        Oct                  Oct
10 2020-11-30        Nov                  Nov
11 2020-12-31        Dec                  Dec
Answered By: Umar.H

the best way would be to do with month_name() as commented by
Nurul Akter Towhid.

df[‘Month’] = df.Month.dt.month_name()

Answered By: bI_jOdev

First you need to strip "0 " in the beginning (as u might get the exception leading zeros in decimal integer literals are not permitted; use an 0o prefix for octal integers)

step1)

def func(i):
    if i[0] == '0':
        i = i[1]
    return(i)
df["Month"] = df["Month"].apply(lambda x: func(x))

Step2:

df["Month"] = df["Month"].apply(lambda x: calendar.month_name(x))

 
Answered By: Shravan Kumar