如何在转换条件下转换熊猫分组?



我有一个包含会话和出价数据的数据框,其中有三列(感兴趣的(:user_id、事件和日期。

  • user_id只是一个用于标识用户的 ID
  • 事件是出价或会话
  • 日期
  • 是一个日期时间对象

现在我要做的是向数据帧添加一列,即第一次出价的日期。我已经尝试了几种方法使其正常工作,但问题是用户在出价之前生成会话当然很常见。

我已经尝试了几种方法让过滤器工作,但它似乎不像我认为的那样工作。从文档中,它说"返回数据帧的副本,排除不满足 func 指定的布尔条件的组中的元素",这听起来像我想要的,忽略组中是会话而不是出价的事件。

df['first bid date'] = df.groupby('user_id').filter(lambda x: x['event'] == 'bid')['date'].transform('min') 

当这不起作用时,我试图让转换采用自定义函数,如下所示:

def custom_transform(group):
return group[group['event'] == 'bid']['date'].min()

df['first bid date'] = df.groupby('user_id').['date'].transform(custom_transform)

但这不起作用,因为转换无法同时访问日期和事件,似乎无论我按什么分组。

最后,我尝试按user_id和事件进行分组,就像这样

df['first bid date'] = df.groupby(['user_id', 'event'])['date'].transform('min')

哪种有效,但是我不得不将所有第一个会话更改为第一个出价,因为现在有一个第一个会话和一个第一个出价。

有什么输入可以使这个单行工作吗?似乎分组、过滤和转换的组合应该可以解决问题,但我就是无法破解它。

谢谢!

想法是在transform之前将不匹配的值替换为缺失值,此处为Series.where

df['first bid date'] = (df.assign(date = df['date'].where(df['event'] == 'bid'))
.groupby('user_id')['date']
.transform('min'))

下面是一些示例代码,其中包含与问题匹配的数据帧。

from io import StringIO
csv = StringIO("""index,uid,event,date
0,1,"bid",'2010-01-01'
1,1,"bid",'2013-01-01'
2,1,"session",'2009-01-01'
3,2,"session",'2010-01-01'
4,2,"bid",'2015-01-01'
5,2,"bid",'2017-01-01'""")
df = pd.read_csv(csv, index_col='index').reset_index(drop=True)

此替代方法使用merge函数。

df.merge(df[df['event']=='bid'].groupby('uid')['date'].min(),
on='uid', suffixes=('','_first_bid'))

哪些打印:

uid  event    date        date_first_bid
0   1    bid      2010-01-01  2010-01-01
1   1    bid      2013-01-01  2010-01-01
2   1    session  2009-01-01  2010-01-01
3   2    session  2010-01-01  2015-01-01
4   2    bid      2015-01-01  2015-01-01
5   2    bid      2017-01-01  2015-01-01

最新更新