代码之家  ›  专栏  ›  技术社区  ›  Richard

大熊猫:从表中分组并查找最近的事件,然后加入现有的表?

  •  2
  • Richard  · 技术社区  · 6 年前

    我有两张熊猫桌,一张 user 表和A history 表-后者本质上是用户所采取的所有操作的日志。

    用户表:

       |  user_id  |  source
    0  |  1        |  blog
    1  |  2        |  blog
    2  |  3        |  organic
    

    历史记录表:

       |  user_id  |  action_type  |  t_actioned
    0  |  1        |  332          |  2018-08-04 12:35:23   
    1  |  1        |  453          |  2018-08-04 12:36:23   
    2  |  1        |  332          |  2018-08-04 12:38:23   
    3  |  2        |  452          |  2018-08-04 12:40:23   
    4  |  3        |  523          |  2018-08-04 12:41:23   
    5  |  2        |  452          |  2018-08-04 12:41:43   
    

    我想从 历史 表,并将其添加到 用户 表作为新列。

    我该怎么做?

    看着 this answer ,我想是这样的:

     # Get the latest action by user
     first_action = history.group_by('user_id').agg(lambda df: df.sort('t_actioned')[-1:].values[0])
     user.first_action = # join with first_action somehow?
    

    但是 agg 查询对我不起作用,我不知道下一步该怎么做。

    3 回复  |  直到 6 年前
        1
  •  4
  •   jpp    6 年前

    首先排序、删除重复项并从历史数据框中创建序列:

    s = history.sort_values('t_actioned', ascending=False)\
               .drop_duplicates('user_id')\
               .set_index('user_id')['action_type']
    

    然后将其映射到您的用户数据框:

    user['action_type'] = user['user_id'].map(s)
    

    正如注释中指出的,如果日志已经排序,则可以避免 sort_values 和使用 drop_duplicates('user_id', keep='last')

        2
  •  3
  •   piRSquared    6 年前

    您可以利用这样一个事实:当用多个重复键构造一个字典时,您只保留最后一个键。

    m = dict(history.sort_values('t_actioned').pipe(
        lambda d: zip(d.user_id, d.t_actioned)))
    
    user.assign(latest=user.user_id.map(m))
    
       user_id   source               latest
    0        1     blog  2018-08-04 12:38:23
    1        2     blog  2018-08-04 12:41:43
    2        3  organic  2018-08-04 12:41:23
    

    考虑数据的短版本已经按 't_actioned'

    user.assign(latest=user.user_id.map(dict(zip(history.user_id, history.t_actioned))))
    
        3
  •  0
  •   Ankur Sinha    6 年前

    另一种方式:

    history = history.groupby(['user_id']).apply(lambda x: x.sort_values('t_actioned', ascending = False))
    history = history.drop_duplicates(subset = ['user_id'], keep = 'first')
    user = pd.merge(user, history[['t_actioned']], on = 'user_id', how = 'left')
    

    输出:

       user_id   source          t_actioned
    0        1     blog 2018-08-04 12:38:23
    1        2     blog 2018-08-04 12:41:43
    2        3  organic 2018-08-04 12:41:23