如果日期在被评估的当前行之前,则分组依据中的行数

问题描述

我想通过 customer_id 计算 num_opens_at_campaign_send。这取决于客户在发送每个广告系列之前已打开的广告系列数量

我无法找出在 Pandas 中执行此操作的最佳方法,因此将不胜感激。我正在考虑使用 groupby customer_idapply 函数来将每个 campaign_sent 日期与该列中的所有其他日期进行比较,但我不确定获取行数的精确方法计算发送每个广告系列时客户已打开的广告系列数量

数据框如下:

customer_id campaign_id campaign_sent 打开
1234 2021-01-01 真的
b 1234 2021-01-01 真的
c 1234 2021-01-01 错误
2222 2021-02-01 真的
b 2222 2021-02-01 错误
c 2222 2021-02-01 真的
3333 2021-03-01 真的
b 3333 2021-03-01 错误
c 3333 2021-03-01 真的

所需的输出是:

customer_id campaign_id campaign_sent num_opens_at_campaign_send
1234 2021-01-01 0
b 1234 2021-01-01 0
c 1234 2021-01-01 0
2222 2021-02-01 1
b 2222 2021-02-01 1
c 2222 2021-02-01 0
3333 2021-03-01 2
b 3333 2021-03-01 1
c 3333 2021-03-01 1

因此对于第一个广告系列,num_opens_at_campaign_send 全部为 0,因为之前没有广告系列。

例如,当发送 customer_id 3333 时,campaign_id 'b' 有 1 个打开,因为他们打开了第一个营销活动 (1234) 但没有打开第二个营销活动 (2222) 电子邮件

解决方法

您可以使用 .groupby.transform 来计算 num_opens_at_campaign_send 列。 customer_id 的第一组,现在 num_opens_at_campaign_send 为一行是 cumulative sum of opened till the row - value of opened in that row

要确保按正确的日期顺序计算 cumulative sum,首先按 campaign_sent 列对数据框进行排序。

使用:

df = df.sort_values(by = ['campaign_sent'])
df['num_opens_at_campaign_send'] = ( df.groupby('customer_id')['opened']
                                       .cumsum() - df.opened)
df.drop(columns = 'opened',inplace = True)

输出:

>>> df
  customer_id  campaign_id campaign_sent  num_opens_at_campaign_send
0           a         1234    2021-01-01                           0
1           b         1234    2021-01-01                           0
2           c         1234    2021-01-01                           0
3           a         2222    2021-02-01                           1
4           b         2222    2021-02-01                           1
5           c         2222    2021-02-01                           0
6           a         3333    2021-03-01                           2
7           b         3333    2021-03-01                           1
8           c         3333    2021-03-01                           1