python/pandas: преобразовать месяц int в название месяца

Большая часть информации, которую я нашел, была не в python > pandas > dataframe, отсюда и вопрос.

Я хочу преобразовать целое число от 1 до 12 в сокращенное название месяца.

У меня есть df, который выглядит так:

   client Month
1  sss    02
2  yyy    12
3  www    06

Я хочу, чтобы df выглядел так:

   client Month
1  sss    Feb
2  yyy    Dec
3  www    Jun

person Boosted_d16    schedule 04.06.2016    source источник


Ответы (11)


Вы можете сделать это эффективно, комбинируя calendar.month_abbr и df[col].apply().

import calendar
df['Month'] = df['Month'].apply(lambda x: calendar.month_abbr[x])
person EoinS    schedule 04.06.2016
comment
Обратите внимание, что это решение похоже на list.__getitem__ в цикле на уровне Python, т. е. оно не использует преимущества векторизованной функциональности, доступной для Pandas. Извлечение в словарь и последующее сопоставление намного эффективнее, согласно этому ответу. - person jpp; 22.01.2019
comment
Я не думаю, что это хорошая идея, пока у вас есть собственная функция month_name() в pandas. - person Nurul Akter Towhid; 24.12.2019

Поскольку сокращенные названия месяцев представляют собой первые три буквы их полных имен, мы могли бы сначала преобразовать столбец Month в datetime, а затем использовать dt.month_name() для получения полного названия месяца и, наконец, использовать метод str.slice() для получения первых трех букв, все с использованием панд и только в одной строке кода:

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
person today    schedule 10.11.2018

Вы можете легко сделать это с применением столбца.

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
person andrew    schedule 04.06.2016

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

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

Ссылка:

person Suhas_Pote    schedule 24.01.2019

Один из способов сделать это — использовать метод apply в фрейме данных, но для этого вам нужна карта для преобразования месяцев. Вы можете сделать это либо с помощью функции/словаря, либо с собственной датой и временем Python.

С datetime это будет что-то вроде:

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)


Аналогичным образом вы можете создать свою собственную карту для пользовательских имен. Это будет выглядеть так:

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


Очевидно, вам не нужно явно определять эти функции, и вы можете использовать lambda непосредственно в методе применения.

person pekapa    schedule 04.06.2016

Используйте для этого функции strptime и lambda:

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

Модуль calendar полезен, но calendar.month_abbr похож на массив: его нельзя использовать напрямую в векторном виде. Для эффективного сопоставления вы можете создать словарь, а затем использовать pd.Series.map:

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

Сравнительный анализ производительности показывает разницу в производительности примерно в 130 раз:

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
person jpp    schedule 22.01.2019

Предположим, у нас есть такой DF, и Date уже находится в формате DateTime:

df.head(3)


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

Затем мы можем легко извлечь номер месяца и название месяца следующим образом:

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
person Abhishek Sengupta    schedule 21.08.2020

использование методов объекта datetime

Я удивлен, что этот ответ не имеет решения с использованием strftime

обратите внимание, что перед использованием метода strftime вам необходимо иметь действительный объект datetime, используйте pd.to_datetime(df['date_column']), чтобы привести целевой столбец к объекту datetime.

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

другой метод - нарезать имя с помощью 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
person Umar.H    schedule 15.01.2021

Протестировав все это на большом наборе данных, я обнаружил, что быстрее всего работает следующее:

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)
person Heather    schedule 23.10.2018

Вы можете использовать функцию Pandas month_name(). Пример:

>>> 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')

Для получения более подробной информации посетите эту ссылку.

person Nurul Akter Towhid    schedule 24.12.2019