Pandas与groupby的部分元素的累积和

时间:2016-11-22 23:59:11

标签: python pandas

如果已经提出这个问题,请道歉,但提前感谢您的帮助。

在这个" unpivoted"数据集中,有 Lots 组成的订单。每个 Lot 都有一个给定的 Point 值,如下所示:

CustID     Date         OrderNum   LotNum   PtsPerLot
A123       1/1/2015     1234       A        2            
A123       1/1/2015     1234       B        10
A123       1/1/2015     5678       A        7

我的目标是在每个CUMULATIVE_POINTS_PER_YEAR级别创建一个POINTS_PER_ORDER列,表示PtsPerLot的累计总和,它本身就是Lot的总和。因此,对于给定的批次,CumPtsPerYear会显示给定年份中帐户的所有POINTS_PER_ORDER的累计总数。

CustID     Date         OrderNum   LotNum   PtsPerLot    *PtsPerOrder*    *CumPtsPerYear*
A123       1/1/2015     1234       A        2            12              12
A123       1/1/2015     1234       B        10           12              12
A123       1/1/2015     5678       A        7            7               19

有什么想法吗?我在groupby.cumsum上尝试了PtsPerLot,在groupby.cumsum上尝试了另一个PtsPerOrder,但它并没有产生我需要的东西。

3 个答案:

答案 0 :(得分:1)

首先,您需要使用transformation

df['*PtsPerOrder*'] = df.groupby('OrderNum')['PtsPerLot'].transform(sum)

然后,为了创建另一个,我没有找到另一种方法来找到每个组的最大值,对其做一个cumsum,并将其合并回来:

weird_cumsum = df.groupby('OrderNum')['*PtsPerOrder*'].max().cumsum().to_frame()
weird_cumsum.columns = ['*CumPtsPerYear*']
weird_cumsum

          *CumPtsPerYear*
OrderNum                 
1234                   12
5678                   19

df.merge(weird_cumsum, left_on='OrderNum', right_index=True, how='left')

结果符合预期:

  CustID       Date  OrderNum LotNum  PtsPerLot  *PtsPerOrder*  *CumPtsPerYear* 
0   A123 2015-01-01      1234      A          2             12             12  
1   A123 2015-01-01      1234      B         10             12             12   
2   A123 2015-01-01      5678      A          7              7             19   

答案 1 :(得分:1)

首先,计算PtsPerOrder。在数据框的实际索引中使用transform 广播,即每组中的计算结果:

df['PtsPerOrder'] = df.groupby('OrderNum')['PtsPerLot'].transform(sum)

然后在每个组中获取该新列的第一个元素:

df['CumPtsPerYear'] = df.groupby('OrderNum')['PtsPerOrder'].head(1)

df
Out[27]: 
  CustID      Date  OrderNum LotNum  PtsPerLot  PtsPerOrder  CumPtsPerYear
0   A123  1/1/2015      1234      A          2           12           12.0
1   A123  1/1/2015      1234      B         10           12            NaN
2   A123  1/1/2015      5678      A          7            7            7.0

通过执行您要搜索的累计金额来结束计算。它将跳过NA值。您可以使用向前填充来完成数据框:

df['CumPtsPerYear'].cumsum().ffill()

0    12.0
1    12.0
2    19.0

答案 2 :(得分:0)

要了解问题的第一部分PtsPerOrder,您需要转换sum是一个聚合。所以使用.transform

In [10]: df
Out[10]:
            Date  OrderNum LotNum  PtsPerLot
CustID
A123    1/1/2015      1234      A          2
A123    1/1/2015      1234      B         10
A123    1/1/2015      5678      A          7

In [11]: df.groupby('OrderNum')['PtsPerLot'].transform('sum')
Out[11]:
CustID
A123    12
A123    12
A123     7
dtype: int64

并使用它来创建一个新列......

In [13]: df['PtsPerOrder'] = df.groupby('OrderNum')['PtsPerLot'].transform('sum')

In [14]: df
Out[14]:
            Date  OrderNum LotNum  PtsPerLot  PtsPerOrder
CustID
A123    1/1/2015      1234      A          2           12
A123    1/1/2015      1234      B         10           12
A123    1/1/2015      5678      A          7            7

我仍然没有按照你的CumPtsPerYear规范......