在DataFrame中嵌套groupby并聚合多个列

问题描述 投票:-1回答:2

我试图做嵌套groupby如下:

>>> df1 = pd.DataFrame({'Date': {0: '2016-10-11', 1: '2016-10-11', 2: '2016-10-11', 3: '2016-10-11', 4: '2016-10-11',5: '2016-10-12'}, 'Stock': {0: 'ABC', 1: 'ABC', 2: 'ABC', 3: 'ABC', 4: 'ABC', 5: 'XYZ'}, 'Quantity': {0: 60,1: 50, 2: 40, 3: 30, 4: 20, 5: 10}, 'UiD':{0:1,1:1,2:1,3:2,4:2,5:3}, 'StartTime': {0: '08:00:00.241', 1: '08:00:00.243', 2: '12:34:23.563', 3: '08:14.05.908', 4: '18:54:50.100', 5: '10:08:36.657'}, 'Sign':{0:1,1:1,2:0,3:-1,4:0,5:-1}, 'leg1':{0:2,1:2,2:4,3:5,4:7,5:8}})
>>> df1
         Date  Quantity  Sign     StartTime Stock  UiD  leg1
0  2016-10-11        60     1  08:00:00.241   ABC    1     2
1  2016-10-11        50     1  08:00:00.243   ABC    1     2
2  2016-10-11        40     0  12:34:23.563   ABC    1     4
3  2016-10-11        30    -1  08:14.05.908   ABC    2     5
4  2016-10-11        20     0  18:54:50.100   ABC    2     7
5  2016-10-12        10    -1  10:08:36.657   XYZ    3     8
>>> dfg1=df1.groupby(['Date','Stock'])
>>> dfg1.apply(lambda x:x.groupby('UiD').first()).groupby(['Date','Stock']).apply(lambda x:np.sum(x['Quantity']))
Date        Stock
2016-10-11  ABC      90
2016-10-12  XYZ      10
dtype: int64
>>>
>>> dfg1['leg1'].sum()
Date        Stock
2016-10-11  ABC      20
2016-10-12  XYZ       8
Name: leg1, dtype: int64

到现在为止还挺好。现在我尝试将两个结果连接成一个新的DataFrame df2,如下所示:

>>> df2 = pd.concat([dfg1['leg1'].sum(), dfg1.apply(lambda x:x.groupby('UiD').first()).groupby(['Date','Stock']).apply(lambda x:np.sum(x['Quantity']))],axis=1)
                   0   1
Date       Stock        
2016-10-11 ABC    20  90
2016-10-12 XYZ     8  10
>>>

我想知道是否有更好的方法来重写下一行,以避免重复groupby(['Date','Stock'])

dfg1.apply(lambda x:x.groupby('UiD').first()).groupby(['Date','Stock']).apply(lambda x:np.sum(x['Quantity']))

如果['Date','Stock']包含'UiD'作为关键之一或['Date','Stock']['UiD']替换,这也失败了。

pandas dataframe group-by nested aggregate
2个回答
1
投票

请重申您的问题以便更清楚。你想要groupby(['Date','Stock']),然后:

  1. 只取每个UiD的第一个记录并总和(汇总)其数量,但也
  2. 汇总该日期,股票组合的所有leg1值(不仅仅是每个UiD的第一个)。是对的吗?

无论如何你想在多个列上执行聚合(求和),是的,避免重复groupby(['Date','Stock'])的方法是保留一个数据帧,而不是试图将两个数据帧拼接在一起集合运营。类似下面的内容(一旦你确认这是你想要的,我会解决它):

def filter_first_UiD(g):
    #return g.groupby('UiD').first().agg(np.sum)
    return g.groupby('UiD').first().agg({'Quantity':'sum', 'leg1':'sum'})

df1.groupby(['Date','Stock']).apply(filter_first_UiD)

0
投票

如果['Date','Stock']包含'UiD'作为其中一个键或['Date','Stock']['UiD']替换,我处理避免groupby失败的最后一个场景的方式如下:

>>> df2 = pd.concat([dfg1['leg1'].sum(), dfg1[].first() if 'UiD' in `['Date','Stock']` else dfg1.apply(lambda x:x.groupby('UiD').first()).groupby(['Date','Stock']).apply(lambda x:np.sum(x['Quantity']))],axis=1)

但更优雅的解决方案仍是一个悬而未决的问题

© www.soinside.com 2019 - 2024. All rights reserved.