Pandas: сгруппируйте и найдите самое последнее событие из таблицы, а затем присоединитесь к существующей таблице?

У меня есть две таблицы в пандах, таблица user и таблица 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   

Я хотел бы найти метку времени последнего действия, предпринятого каждым пользователем, из таблицы history и добавить ее в таблицу user в качестве нового столбца.

Как я могу это сделать?

Глядя на этот ответ, я думаю, что это что-то вроде:

 # 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 у меня не работает, и я не уверен, что делать дальше.

2
0
70
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Ответ принят как подходящий

Сначала отсортируйте, отбросьте дубликаты и создайте серию из фрейма данных истории:

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').

Если вы предполагаете, что они уже отсортированы, вы также можете просто сделать drop_duplicates(keep='last')

piRSquared 10.08.2018 17:10

Вы можете воспользоваться тем фактом, что при создании словаря с несколькими повторяющимися ключами вы сохраните только последний.

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))))

Другой путь:

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

Другие вопросы по теме