按月份名称和年份对大熊猫输出分组

时间:2020-01-05 13:17:30

标签: python pandas calendar

df

order_date    Month Name   Year   Days  Data
2015-12-20     Dec         2014    1     3
2016-1-21      Jan         2014    2     3
2015-08-20     Aug         2015    1     1 
2016-04-12     Apr         2016    4     1

and so on

代码:

df = df.groupby(["Year", "Month Name"], as_index=False)["days"].agg(['min', 
'mean'])
df3 = (df.groupby(["Year", "Month Name"], as_index=False) 
["Data"].agg(['count']))
merged_df=pd.merge(df3, df, on=['Year','Month Name'])

我有如下的groupby输出

                    Min Mean    Count
Year    Month Name                  
2015    Aug          2    11      200
        Dec          5    13      130
        Feb          3    15      100
        Jan          4    20      123
        May          1    21      342
        Nov          2    12      234
 2016   Apr          1    10      200
        Dec          2    12      120
        Feb          2    13      200
        Jan          2    24      200
        Sep          1    25      220

问题:

基本上我得到的是groupby的输出,按月名称从A到Z排序,所以我得到的是4月,8月,12月,2月等……而不是1月,2月....直到12月等。如何获取按月号排序的输出。

需要类似2016年,1月,2月.... 2017年12月,2017年1月,2月,3月至12月的输出

如果合并2个dfs,请提供帮助。我刚刚在这里给出了一个简化的代码(实际代码是不同的,我需要将两者合并,然后只有我才能工作)

3 个答案:

答案 0 :(得分:2)

只需告诉groupby您不希望它对组密钥进行排序(默认情况下就是这样-请参见the docs

df.groupby(["Year", "Month Name"], as_index=False, sort=False)["Days"].agg(
    ["min", "mean"]
)

注意:在应用分组方式之前,您应确保df已排序

答案 1 :(得分:2)

编辑:您的解决方案应更改:

df1 = df.groupby(["Year", "Month Name"], as_index=False)["Days"].agg(['min', 'mean'])
df3 = df.groupby(["Year", "Month Name"], as_index=False)["Data"].agg(['count'])
merged_df=pd.merge(df3, df1, on=['Year','Month Name']).reset_index()

cats = ['Jan', 'Feb', 'Mar', 'Apr','May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']
merged_df['Month Name'] = pd.Categorical(merged_df['Month Name'],categories=cats, ordered=True)

merged_df = merged_df.sort_values(["Year", "Month Name"])
print (merged_df)
   Year Month Name  count  min  mean
1  2014        Jan      1    2     2
0  2014        Dec      1    1     1
2  2015        Aug      1    1     1
3  2016        Apr      1    4     4

或者:

df1 = (df.groupby(["Year", "Month Name"])
         .agg(min_days=("Days", 'min'),
              avg_days=("Days", 'mean'),
              count = ('Data', 'count'))
         .reset_index())

cats = ['Jan', 'Feb', 'Mar', 'Apr','May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']
df1['Month Name'] = pd.Categorical(df1['Month Name'], categories=cats, ordered=True)

df1 = df1.sort_values(["Year", "Month Name"])
print (df1)
   Year Month Name  min_days  avg_days  count
1  2014        Jan         2         2      1
0  2014        Dec         1         1      1
2  2015        Aug         1         1      1
3  2016        Apr         4         4      1

最后一个带有MultiIndex并且没有分类的解决方案,该解决方案创建了助手日期列并对其进行排序:

df1 = (df.groupby(["Year", "Month Name"])
         .agg(min_days=("Days", 'min'),
              avg_days=("Days", 'mean'),
              count = ('Data', 'count'))
        )


df1['dates'] = pd.to_datetime([f'{y}{m}' for y, m in df1.index], format='%Y%b')
df1 = df1.sort_values('dates')
print (df1)
                 min_days  avg_days  count      dates
Year Month Name                                      
2014 Jan                2         2      1 2014-01-01
     Dec                1         1      1 2014-12-01
2015 Aug                1         1      1 2015-08-01
2016 Apr                4         4      1 2016-04-01

答案 2 :(得分:1)

这是我的解决方案,按月号排序并返回level=1作为输入的多索引merged_df的排序月名称:

import calendar
d={i:e for e,i in enumerate([*calendar.month_abbr])}
#for full month name use :-> d={i:e for e,i in enumerate([*calendar.month_name])} 

merged_df.index=pd.MultiIndex.from_tuples(sorted(merged_df.index,key=lambda x: d.get(x[1])))
merged_df = merged_df.sort_index(level=0)

print(merged_df)
                 count  min  mean
Year Month Name                  
2014 Jan             1    2     2
     Dec             1    1     1
2015 Aug             1    1     1
2016 Apr             1    4     4