Python 仅适用于所有以前的值的条件运行求和

Python 仅适用于所有以前的值的条件运行求和,python,pandas,grouping,cumulative-sum,Python,Pandas,Grouping,Cumulative Sum,假设我有以下数据帧: df = pd.DataFrame({'Event': ['A', 'B', 'A', 'A', 'B', 'C', 'B', 'B', 'A', 'C'], 'Date': ['2019-01-01', '2019-02-01', '2019-03-01', '2019-03-01', '2019-02-15', '2019-03-15', '2019-04-05', '2

假设我有以下数据帧:

df = pd.DataFrame({'Event': ['A', 'B', 'A', 'A', 'B', 'C', 'B', 'B', 'A', 'C'], 
                   'Date': ['2019-01-01', '2019-02-01', '2019-03-01', '2019-03-01', '2019-02-15', 
                             '2019-03-15', '2019-04-05', '2019-04-05', '2019-04-15', '2019-06-10'],
                   'Sale': [100, 200, 150, 200, 150, 100, 300, 250, 500, 400]})
df['Date'] = pd.to_datetime(df['Date'])
df

Event         Date  Sale
    A   2019-01-01   100
    B   2019-02-01   200
    A   2019-03-01   150
    A   2019-03-01   200
    B   2019-02-15   150
    C   2019-03-15   100
    B   2019-04-05   300
    B   2019-04-05   250
    A   2019-04-15   500
    C   2019-06-10   400
我希望得到以下结果:

Event         Date  Sale   Total_Previous_Sale
    A   2019-01-01   100                     0
    B   2019-02-01   200                     0
    A   2019-03-01   150                   100
    A   2019-03-01   200                   100
    B   2019-02-15   150                   200
    C   2019-03-15   100                     0
    B   2019-04-05   300                   350
    B   2019-04-05   250                   350
    A   2019-04-15   500                   450
    C   2019-06-10   400                   100
其中,
df['Total_Previous_Sale']
是事件(
df['Sale']
)在其相邻日期(
df['date']
)之前发生时的总销售额(
df['Sale']
)。比如说,

  • 2019-01-01年之前发生的活动A的销售总额为0
  • 2019-03-01年之前发生的活动A的销售总额为100,且
  • 2019-04-15年之前发生的活动A的销售总额为100+150+200=450
基本上,它与条件累积和几乎相同,但仅适用于所有以前的值(不包括当前值)。我能够使用这一行获得所需的结果:

df['Sale_Total'] = [df.loc[(df['Event'] == df.loc[i, 'Event']) & (df['Date'] < df.loc[i, 'Date']), 
                           'Sale'].sum() for i in range(len(df))]

但它会产生NaN或产生不想要的结果。

对于
多索引
,首先对每个
事件进行聚合
求和
日期
,然后按一级
事件
进行分组,并使用
shift
和lambda函数的累积和,最后将
连接在一起:

s = (df.groupby(['Event', 'Date'])['Sale']
       .sum().groupby(level=0)
       .apply(lambda x: x.shift(1).cumsum())
       .fillna(0)

df = df.join(s.rename('Total_Previuos_Sale'), on=['Event','Date'])
print (df)
  Event        Date  Sale  Total_Previuos_Sale
0     A  2019-01-01   100                  0.0
1     B  2019-02-01   200                  0.0
2     A  2019-03-01   150                100.0
3     A  2019-03-01   200                100.0
4     B  2019-02-15   150                200.0
5     C  2019-03-15   100                  0.0
6     B  2019-04-05   300                350.0
7     B  2019-04-05   250                350.0
8     A  2019-04-15   500                450.0
9     C  2019-06-10   400                100.0

最后,我可以找到一个更好更快的方法来获得想要的结果。事实证明这很容易。你可以试试:

df['Total_Previous_Sale'] = df.groupby('Event')['Sale'].cumsum() \
                          - df.groupby(['Event', 'Date'])['Sale'].cumsum()

啊,谢谢你的回答。看来你的技巧也可以用来回答问题。请您回答好吗?
s = (df.groupby(['Event', 'Date'])['Sale']
       .sum().groupby(level=0)
       .apply(lambda x: x.shift(1).cumsum())
       .fillna(0)

df = df.join(s.rename('Total_Previuos_Sale'), on=['Event','Date'])
print (df)
  Event        Date  Sale  Total_Previuos_Sale
0     A  2019-01-01   100                  0.0
1     B  2019-02-01   200                  0.0
2     A  2019-03-01   150                100.0
3     A  2019-03-01   200                100.0
4     B  2019-02-15   150                200.0
5     C  2019-03-15   100                  0.0
6     B  2019-04-05   300                350.0
7     B  2019-04-05   250                350.0
8     A  2019-04-15   500                450.0
9     C  2019-06-10   400                100.0
df['Total_Previous_Sale'] = df.groupby('Event')['Sale'].cumsum() \
                          - df.groupby(['Event', 'Date'])['Sale'].cumsum()