python/pandas:将月份int转换为月份名称

python/pandas:将月份int转换为月份名称,python,date,pandas,dataframe,monthcalendar,Python,Date,Pandas,Dataframe,Monthcalendar,我发现的大部分信息都不在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 months_map = {01: 'Jan', 02: 'Fe

我发现的大部分信息都不在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
months_map = {01: 'Jan', 02: 'Feb'}
def mapper(month):
    return months_map[month]

使用“应用”列可以轻松完成此操作

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

一种方法是在数据帧中使用
apply
方法,但要做到这一点,您需要一个映射来转换月份。您可以使用函数/字典或Python自己的datetime来实现这一点

使用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)

同样,您可以为自定义名称构建自己的映射。它看起来是这样的:

   client Month
1  sss    Feb
2  yyy    Dec
3  www    Jun
months_map = {01: 'Jan', 02: 'Feb'}
def mapper(month):
    return months_map[month]


显然,您不需要显式定义此函数,并且可以在apply方法中直接使用
lambda

您可以通过将
calendar.month\u abbr
df[col].apply()组合起来有效地实现这一点


为此使用
strtime
lambda
功能:

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

在一个大型数据集上测试了所有这些,我发现以下是最快的:

导入日历
def month_mapping():
#我很懒,所以我有一堆已经写过的函数
#我不必每次都写出来。这将返回
#{1:'Jan'..12:'Dec'}以最懒的方式口述。。。
abbrevs={}
对于范围(1,13)内的月份:
abbrevs[month]=日历月
返回abbrevs
abbrevs=月份映射()
df['Month Abbrev'}=df['Date Col'].dt.Month.map(映射)

由于缩写的月份名称是其全名的前三个字母,我们可以首先将
month
列转换为
datetime
,然后使用
dt.month\u 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
该模块很有用,但类似于数组:它不能以矢量化方式直接使用。为了高效映射,您可以构造一个字典,然后使用
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
参考:


您可以使用Pandas
month\u name()
函数。示例:

>idx=pd.日期范围(开始时间=2018-01',频率=M',周期=3)
>>>idx
日期时间索引(['2018-01-31','2018-02-28','2018-03-31'],
dtype='datetime64[ns]',freq='M')
>>>idx.month_name()
索引(['一月','二月','三月'],dtype='object')

有关更多详细信息,请访问。

假设我们有这样一个DF,并且日期已经是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
使用datetime对象方法 我很惊讶这个答案没有使用strftime的解决方案

注意,在使用
strftime
方法之前,您需要有一个有效的datetime对象,使用
pd.to\u datetime(df['date\u 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\u name()


请注意,此解决方案类似于Python级别的循环中的
list.\uuuu getitem\uuuuu
,即它没有利用Pandas可用的矢量化功能。根据,提取到字典,然后映射要高效得多。我认为如果您有Pandas自己的month\u 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