用Pythonic/Panda方法创建Groupby函数 [英] Pythonic / Panda Way to Create Function to Groupby

查看:93
本文介绍了用Pythonic/Panda方法创建Groupby函数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我对编程&尚不陌生.我正在寻找一种更pythonic的方式来实现一些代码.这是虚拟数据:

I am fairly new to programming & am looking for a more pythonic way to implement some code. Here is dummy data:

 df = pd.DataFrame({
'Category':np.random.choice( ['Group A','Group B'], 10000),
'Sub-Category':np.random.choice( ['X','Y','Z'], 10000),
'Sub-Category-2':np.random.choice( ['G','F','I'], 10000),
'Product':np.random.choice( ['Product 1','Product 2','Product 3'], 10000),
'Units_Sold':np.random.randint(1,100, size=(10000)),
'Dollars_Sold':np.random.randint(100,1000, size=10000), 
'Customer':np.random.choice(pd.util.testing.rands_array(10,25,dtype='str'),10000),
'Date':np.random.choice( pd.date_range('1/1/2016','12/31/2018',  
                  freq='D'), 10000)})

我有很多交易数据,就像我执行各种Groupby一样.我当前的解决方案是像这样制作一个主分组:

I have lots of transactional data like that that I perform various Groupby's on. My current solution is to make a master groupby like this:

master = df.groupby(['Customer','Category','Sub-Category','Product',pd.Grouper(key='Date',freq='A')])['Units_Sold'].sum()\
.unstack()

从那里,我使用.groupby(level =)函数执行各种groupby,以按照所需的方式汇总信息.我通常在每个级别上进行总结.另外,我使用以下代码的一些变体在每个级别创建小计.

From there, I perform various groupbys using .groupby(level=) function to aggregate the information in the way I'm looking for. I usually make a summary at each level. In addition, I create sub-totals at each level using some variation of the below code.

y = master.groupby(level=[0,1,2]).sum()
y.index = pd.MultiIndex.from_arrays([
    y.index.get_level_values(0),
    y.index.get_level_values(1),
    y.index.get_level_values(2) + ' Total',
    len(y.index)*['']
])

y1 = master.groupby(level=[0,1]).sum()
y1.index = pd.MultiIndex.from_arrays([
    y1.index.get_level_values(0),
    y1.index.get_level_values(1)+ ' Total',
    len(y1.index)*[''],
    len(y1.index)*['']
])

y2 = master.groupby(level=[0]).sum()
y2.index = pd.MultiIndex.from_arrays([
    y2.index.get_level_values(0)+ ' Total',
    len(y2.index)*[''],
    len(y2.index)*[''],
    len(y2.index)*['']
])

pd.concat([master,y,y1,y2]).sort_index()\
    .assign(Diff = lambda x: x.iloc[:,-1] - x.iloc[:,-2])\
    .assign(Diff_Perc = lambda x: (x.iloc[:,-2] / x.iloc[:,-3])- 1)\
    .dropna(how='all')\

这只是一个例子-我可能执行相同的练习,但是以不同的顺序执行分组.例如-接下来,我可能想按类别",产品",然后是客户"进行分组,所以我必须这样做: master.groupby(level = [1,3,0).sum()

This is just an example - I may perform the same exercise, but perform the groupby in a different order. For example - next I may want to group by 'Category', 'Product', then 'Customer', so I'd have to do: master.groupby(level=[1,3,0).sum()

然后,我将不得不对上述小计重复整个练习.我还经常更改时间段-可能是特定月份的年末,可能是年初至今,可能是按季度等等.

Then I will have to repeat the whole exercise for sub-totals like above. I also frequently change the time period - could be year-ending a specific month, could be year to date, could be by quarter, etc.

根据我到目前为止在编程中所学的知识(很明显,这是最少的),您应该在每次重复代码时都编写一个函数.显然,我在&重复代码在此示例中再次说明.

From what I've learned so far in programming (which is minimal, clearly!), you should look to write a function any time you repeat code. Obviously I am repeating code over & over again in this example.

有没有一种方法可以构造一个功能,您可以在向Groupby提供级别的同时提供时间框架,同时还可以创建一个对每个级别进行小计的功能?

Is there a way to construct a function where you can provide the levels to Groupby, along with the time frame, all while creating a function for sub-totaling each level as well?

在此先感谢您提供任何指导.这是非常赞赏.

Thanks in advance for any guidance on this. It is very much appreciated.

推荐答案

对于DRY-er解决方案,请考虑将当前方法推广到已定义的模块中,该模块按日期范围过滤原始数据帧并运行汇总,并接收group_by参数中传递的级别和日期范围(后为可选):

For a DRY-er solution, consider generalizing your current method into a defined module that filters original data frame by date ranges and runs aggregations, receiving the group_by levels and date ranges (latter being optional) as passed in parameters:

方法

def multiple_agg(mylevels, start_date='2016-01-01', end_date='2018-12-31'):

    filter_df = df[df['Date'].between(start_date, end_date)]

    master = (filter_df.groupby(['Customer', 'Category', 'Sub-Category', 'Product', 
                     pd.Grouper(key='Date',freq='A')])['Units_Sold']
                .sum()
                .unstack()
              )

    y = master.groupby(level=mylevels[:-1]).sum()
    y.index = pd.MultiIndex.from_arrays([
        y.index.get_level_values(0),
        y.index.get_level_values(1),
        y.index.get_level_values(2) + ' Total',
        len(y.index)*['']
    ])

    y1 = master.groupby(level=mylevels[0:2]).sum()
    y1.index = pd.MultiIndex.from_arrays([
        y1.index.get_level_values(0),
        y1.index.get_level_values(1)+ ' Total',
        len(y1.index)*[''],
        len(y1.index)*['']
    ])

    y2 = master.groupby(level=mylevels[0]).sum()
    y2.index = pd.MultiIndex.from_arrays([
        y2.index.get_level_values(0)+ ' Total',
        len(y2.index)*[''],
        len(y2.index)*[''],
        len(y2.index)*['']
    ])

    final_df = (pd.concat([master,y,y1,y2])
                         .sort_index()
                         .assign(Diff = lambda x: x.iloc[:,-1] - x.iloc[:,-2])
                         .assign(Diff_Perc = lambda x: (x.iloc[:,-2] / x.iloc[:,-3])- 1)
                         .dropna(how='all')
                         .reorder_levels(mylevels)
                )

    return final_df

汇总运行 (具有不同级别和日期范围)

agg_df1 = multiple_agg([0,1,2,3])

agg_df2 = multiple_agg([1,3,0,2], '2016-01-01', '2017-12-31')

agg_df3 = multiple_agg([2,3,1,0], start_date='2017-01-01', end_date='2018-12-31')

测试 (final_df是OP的pd.concat()输出)

Testing (final_df being OP'S pd.concat() output)

# EQUALITY TESTING OF FIRST 10 ROWS
print(final_df.head(10).eq(agg_df1.head(10)))

# Date                                        2016-12-31 00:00:00  2017-12-31 00:00:00  2018-12-31 00:00:00  Diff  Diff_Perc
# Customer   Category Sub-Category Product                                                                                  
# 45mhn4PU1O Group A  X            Product 1                 True                 True                 True  True       True
#                                  Product 2                 True                 True                 True  True       True
#                                  Product 3                 True                 True                 True  True       True
#                     X Total                                True                 True                 True  True       True
#                     Y            Product 1                 True                 True                 True  True       True
#                                  Product 2                 True                 True                 True  True       True
#                                  Product 3                 True                 True                 True  True       True
#                     Y Total                                True                 True                 True  True       True
#                     Z            Product 1                 True                 True                 True  True       True
#                                  Product 2                 True                 True                 True  True       True

这篇关于用Pythonic/Panda方法创建Groupby函数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆