如何在转换条件下转换大熊猫groupby?

时间:2020-05-15 08:46:32

标签: python pandas dataframe filter transform

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

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

现在我要做的是在数据框中添加一栏,即第一笔出价的日期。我尝试了几种方法来使它起作用,但是问题是,在出价之前,用户通常会生成一个会话。

我已经尝试了几种方法来使过滤器正常工作,但是它似乎不像我认为的那样工作。从文档中说:“返回一个DataFrame的副本,该副本不包括不满足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')

哪种方法有效,但是由于现在有了第一届会议和第一出价,我不得不将所有第一届会议更改为第一出价。

是否有任何投入使oneliner发挥作用?似乎组合了groupby,filter和transform可以解决问题,但我无法破解。

谢谢!

2 个答案:

答案 0 :(得分:1)

想法是将transform之前的不匹配值替换为丢失的值,这里用Series.where

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

答案 1 :(得分:0)

这是一些带有数据框的示例代码,可以解决此问题。

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