将yyyymm格式的列映射到数字列的Pythonic方法?

时间:2019-02-11 17:59:21

标签: python pandas dataframe dictionary

很抱歉,如果标题中的标题不完全清楚,但要点是我有一个熊猫DataFrame,下面是Date列:

 Date
201611
201612
201701

我想映射它,所以我有一个period列,第一个周期的值是1,然后开始一个一个地计数直到最后一个周期,就像这样:

 Date     Period
201611      1
201612      2
201701      3

我实现了我想要做的:

dic_t={}
for n,t in enumerate(sorted(df.Date.unique())):
    dic_t[t]=n+1
df['Period']=df.Date.map(dic_t)

但是它似乎不太pythonic。我想我可以通过字典理解来达到类似的目的,但是我还不擅长

有什么想法吗?

2 个答案:

答案 0 :(得分:2)

pd.factorize可以对项目列表进行排序并返回唯一的整数标签:

In [209]: pd.factorize(['201611','201612','201701','201702','201704','201612'], sort=True)[0]+1
Out[209]: array([1, 2, 3, 4, 5, 2])

因此您可以使用

df['Period'] = pd.factorize(df['Date'], sort=True)[0] + 1

pd.factorize返回标签数组和唯一值数组:

In [210]: pd.factorize(['201611','201612','201701','201702','201704','201612'], sort=True)
Out[210]: 
(array([0, 1, 2, 3, 4, 1]),
 array(['201611', '201612', '201701', '201702', '201704'], dtype=object))

因为这个问题,看来您只想要标签,所以我使用pd.factorize(...)[0]仅获取标签。

答案 1 :(得分:1)

因此,根据问题和评论中的信息,时段的枚举(年和月的组合)应从数据框中出现的第一个时段开始。

为此,您的代码可以正常工作。如果您认为dict的理解看起来是“更pythonic”,则可以将其表示为:

period_dict = {
    period: i+1
    for i, period in enumerate(sorted(df.Date.unique()))}
df['Period'] = df.Date.map(period_dict)

请注意:使用此方法时,如果由于某种原因在开始月份之后的一个月内没有任何数据点,则该月将不会为其分配期间号。 例如,如果您没有2017年3月的数据,则:

 Date     Period
201611      1
201612      2
201701      3
201702      4
201704      5       <== April is period 5 and not 6

如果您需要在所有可能的期间内生成完整的枚举,请使用以下内容:

start_year = 2016
end_year = 2018
period_list = [
    y*100 + m
    for y in range(start_year, end_year+1)
    for m in range(1, 13)]
period_dict = {
    period: i+1
    for i, period in enumerate(period_list)}

df['Period'] = df.Date.map(period_dict)