Объединение двух наборов данных в Datetime - PullRequest
0 голосов
/ 05 июля 2018

У меня есть два набора данных: Первый содержит данные для начала процесса регистрации, а второй - для его окончания. У меня есть идентификаторы пользователей и дата.

Пример первого (начало процесса регистрации):

User ID Time
1111111 2016-01-26 13:02:22
1111111 2016-01-26 14:05:51
1111111 2016-01-26 14:58:08
1111111 2016-01-27 11:17:09
1111111 2016-01-27 12:05:17
1111111 2016-01-27 13:15:33
1111111 2016-01-27 18:10:12
1111111 2016-01-27 20:23:38
222222 2016-01-29 09:01:00
222222 2016-01-29 09:04:15
222222 2016-01-29 11:27:35
222222 2016-01-30 09:02:36
222222 2016-06-29 08:50:02
333333 2016-01-26 09:58:27

И второй (конец процесса регистрации):

User ID Time
1111111 2016-01-26 13:37:54
1111111 2016-01-26 14:40:34
1111111 2016-01-26 15:21:53
1111111 2016-01-27 11:42:58
1111111 2016-01-27 12:43:52
1111111 2016-01-27 13:39:56
1111111 2016-01-27 18:41:01
1111111 2016-01-27 20:51:56
222222 2016-01-29 09:17:26
222222 2016-01-29 11:37:10
222222 2016-01-30 09:16:33
333333 2016-01-29 09:14:39

Мне нужно рассчитать время, необходимое пользователю для завершения процесса регистрации. Проблема в том, что в первом наборе данных гораздо больше строк, чем во втором, поскольку пользователь может запустить процесс, а затем просто отказаться от него, поэтому я не могу просто объединить индекс. например.: Два начала:

222222 2016-01-29 09:01:00
222222 2016-01-29 09:04:15

И только один конец:

222222 2016-01-29 09:17:26

Есть ли хороший способ использовать функцию merge / merge_asof для этого?

1 Ответ

0 голосов
/ 05 июля 2018

IIUUC, вы можете использовать merge_asof. Это позволит вам присоединиться к двум фреймам данных в точных совпадениях для 'User ID' и даты, а затем вы можете выбрать ближайшее время в фрейме данных конца (df_end), то есть после времени в фрейме данных начала (df_beg) )

import pandas as pd

# Need to convert to datetime and sort the keys we will merge_asof on.
df_beg['Time'] = pd.to_datetime(df_beg.Time)
df_end['Time'] = pd.to_datetime(df_end.Time)
df_beg = df_beg.sort_values('Time').rename(columns={'Time': 'Time_start'})
df_end = df_end.sort_values('Time').rename(columns={'Time': 'Time_end'})

merged = pd.merge_asof(df_beg, df_end,
              left_by=['User ID', df_beg.Time_start.dt.date], 
              right_by=['User ID', df_end.Time_end.dt.date],
              left_on='Time_start', right_on='Time_end',
              direction='forward').drop(columns='key_1)

merged сейчас:

    User ID          Time_start            Time_end
0    333333 2016-01-26 09:58:27                 NaT
1   1111111 2016-01-26 13:02:22 2016-01-26 13:37:54
2   1111111 2016-01-26 14:05:51 2016-01-26 14:40:34
3   1111111 2016-01-26 14:58:08 2016-01-26 15:21:53
4   1111111 2016-01-27 11:17:09 2016-01-27 11:42:58
5   1111111 2016-01-27 12:05:17 2016-01-27 12:43:52
6   1111111 2016-01-27 13:15:33 2016-01-27 13:39:56
7   1111111 2016-01-27 18:10:12 2016-01-27 18:41:01
8   1111111 2016-01-27 20:23:38 2016-01-27 20:51:56
9    222222 2016-01-29 09:01:00 2016-01-29 09:17:26
10   222222 2016-01-29 09:04:15 2016-01-29 09:17:26
11   222222 2016-01-29 11:27:35 2016-01-29 11:37:10
12   222222 2016-01-30 09:02:36 2016-01-30 09:16:33
13   222222 2016-06-29 08:50:02                 NaT

Если вам необходимо рассчитать среднее время, как вы указали в комментариях, вам нужно прыгнуть через несколько обручей из-за типа данных timedelta64.

import numpy as np

mask = merged.Time_end.notnull()
# Calculate the time difference and convert to a numeric type
merged.loc[mask, 'Time_diff'] = (merged.loc[mask, 'Time_end'] 
                                 - merged.loc[mask, 'Time_start']).astype(np.int64)

# Calculate the average time difference, convert back to timedelta.
pd.to_timedelta(merged.groupby('User ID').Time_diff.mean())
#User ID
#222222    00:13:17.250000
#333333                NaT
#1111111   00:30:14.250000
#Name: Time_diff, dtype: timedelta64[ns]
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...