Сравнение и ближайшее время, python

Привет, у меня есть набор данных:

BDate,Snum,ArrTime,OID,TDate,TTime,VID
1/1/2018,72,05:59:01,7214,1/1/2018,12:06:20 AM ,7206
1/1/2018,72,06:04:33,7208,1/1/2018,12:36:31 AM,7205
1/1/2018,72,06:21:07,7216,1/1/2018,5:53:49 AM,7220
1/1/2018,80,06:29:01,8026,1/1/2018,5:59:10 AM,7214
1/1/2018,72,06:30:54,7218,1/1/2018,6:04:55 AM,7208
1/1/2018,72,06:33:54,7221,1/1/2018,06:21:17 AM,7216
1/1/2018,80,06:35:26,8018,1/1/2018,06:31:04 AM,7218
1/1/2018,72,09:38:34,7211,1/1/2018,1:40:38 PM,7209
1/1/2018,72,13:39:45,7209,,,

Я хотел бы сделать цикл для соответствия с условием 2 (OID должен быть таким же, как VID, и время ArrTime, чтобы соответствовать ближайшему TTime)

Желаемый результат будет похож на выполнение условия ЕСЛИ.

BDate,Snum,ArrTime,OID,TDate,TTime,VID
1/1/2018,72,05:59:01,7214,1/1/2018,5:59:10 AM,7214
1/1/2018,72,06:04:33,7208,1/1/2018,6:04:55 AM,7208
1/1/2018,72,06:21:07,7216,1/1/2018,06:21:17 AM,7216
1/1/2018,72,06:30:54,7218,1/1/2018,06:31:04 AM,7218
1/1/2018,72,13:39:45,7209,1/1/2018,1:40:38 PM,7209

Еще распечатать это в другом файле

BDate,Snum,ArrTime,OID
1/1/2018,80,06:29:01,8026
1/1/2018,80,06:35:26,8018
1/1/2018,72,09:38:34,7211

Хотел бы спросить, нужно ли мне делать это с помощью Pandas, dataframe или я могу просто сделать это нормально без этой библиотеки. Нужно направление, чтобы начать! Спасибо и обновлю вопрос, если у меня появятся какие-либо коды!

EDITED: дополнительные 2 строки данных с пустым полем

Pandas подойдет для этого.
Mayank Porwal 26.10.2018 08:44
0
1
95
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

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

Используйте merge_asof.

Первый to_datetime с параметром format с mask для правильного формата синтаксического анализа AM/PM:

df['Date1'] = pd.to_datetime(df['BDate'] + ' ' + df['ArrTime'], format='%d/%m/%Y %H:%M:%S')
datesAM = pd.to_datetime(df['TDate'] + ' ' + df['TTime'], format='%d/%m/%Y %I:%M:%S %p')
datesPM = pd.to_datetime(df['TDate'] + ' ' + df['TTime'], format='%d/%m/%Y %H:%M:%S %p')
df['Date2'] = datesAM.mask(df['TTime'].str.endswith('AM', na=False), datesPM)
print (df)
      BDate  Snum   ArrTime   OID     TDate        TTime     VID  \
0  1/1/2018    72  05:59:01  7214  1/1/2018  12:06:20 AM  7206.0   
1  1/1/2018    72  06:04:33  7208  1/1/2018  12:36:31 AM  7205.0   
2  1/1/2018    72  06:21:07  7216  1/1/2018   5:53:49 AM  7220.0   
3  1/1/2018    80  06:29:01  8026  1/1/2018   5:59:10 AM  7214.0   
4  1/1/2018    72  06:30:54  7218  1/1/2018   6:04:55 AM  7208.0   
5  1/1/2018    72  06:33:54  7221  1/1/2018  06:21:17 AM  7216.0   
6  1/1/2018    80  06:35:26  8018  1/1/2018  06:31:04 AM  7218.0   
7  1/1/2018    72  09:38:34  7211  1/1/2018   1:40:38 PM  7209.0   
8  1/1/2018    72  13:39:45  7209       NaN          NaN     NaN   

                Date1               Date2  
0 2018-01-01 05:59:01 2018-01-01 12:06:20  
1 2018-01-01 06:04:33 2018-01-01 12:36:31  
2 2018-01-01 06:21:07 2018-01-01 05:53:49  
3 2018-01-01 06:29:01 2018-01-01 05:59:10  
4 2018-01-01 06:30:54 2018-01-01 06:04:55  
5 2018-01-01 06:33:54 2018-01-01 06:21:17  
6 2018-01-01 06:35:26 2018-01-01 06:31:04  
7 2018-01-01 09:38:34 2018-01-01 13:40:38  
8 2018-01-01 13:39:45                 NaT  

Затем выберите по подмножеству, удалите отсутствующие значения и выполните сортировку:

df1 = df[['Date1','Snum', 'OID']].sort_values('Date1').dropna(subset=['OID'])
df1['OID'] = df1['OID'].astype(np.int64)
print (df1)
                Date1  Snum   OID
0 2018-01-01 05:59:01    72  7214
1 2018-01-01 06:04:33    72  7208
2 2018-01-01 06:21:07    72  7216
3 2018-01-01 06:29:01    80  8026
4 2018-01-01 06:30:54    72  7218
5 2018-01-01 06:33:54    72  7221
6 2018-01-01 06:35:26    80  8018
7 2018-01-01 09:38:34    72  7211
8 2018-01-01 13:39:45    72  7209

df2 = df[['Date2','VID']].sort_values('Date2').dropna(subset=['VID'])
df2['VID'] = df2['VID'].astype(np.int64)
print (df2)
#                Date2   VID
2 2018-01-01 05:53:49  7220
3 2018-01-01 05:59:10  7214
4 2018-01-01 06:04:55  7208
5 2018-01-01 06:21:17  7216
6 2018-01-01 06:31:04  7218
0 2018-01-01 12:06:20  7206
1 2018-01-01 12:36:31  7205
7 2018-01-01 13:40:38  7209

df3 = pd.merge_asof(df1, 
                    df2, 
                    left_on='Date1', 
                    right_on='Date2',
                    left_by='OID',
                    right_by='VID',
                    direction='forward'
                    )

В последнюю очередь удалите недостающие строки и преобразуйте столбец VID в целые числа:

df3 = df3.dropna(subset=['VID'])
df3['VID'] = df3['VID'].astype(int)
print (df3)
                Date1  Snum   OID               Date2   VID
0 2018-01-01 05:59:01    72  7214 2018-01-01 05:59:10  7214
1 2018-01-01 06:04:33    72  7208 2018-01-01 06:04:55  7208
2 2018-01-01 06:21:07    72  7216 2018-01-01 06:21:17  7216
4 2018-01-01 06:30:54    72  7218 2018-01-01 06:31:04  7218
8 2018-01-01 13:39:45    72  7209 2018-01-01 13:40:38  7209

Привет! Ваш код мне очень помог! Но я только что понял, что мои данные включают пустое поле в последние несколько строк. Затем я столкнулся с проблемой слияния. Пожалуйста посоветуй! Обновили вопрос.

ThanksForHelping 26.10.2018 09:56

@ThanksForHelping - у меня 2 вопроса - нужны даты с такими временами, как первое мое решение? А реальные данные - это смешанные данные столбца времени AM с PM в TTime?

jezrael 26.10.2018 10:15

Да, дата и время требуются, и, к сожалению, TTime не в 24-часовом формате, а состоит из AM / PM.

ThanksForHelping 26.10.2018 10:27

@ThanksForHelping - Добавлено новое решение, немного сложное.

jezrael 26.10.2018 10:34

Спасибо за руководство! Это было очень полезно для меня!

ThanksForHelping 26.10.2018 11:08

Привет, @jezrael, я понимаю, что вышеупомянутый вопрос был решен, но хотел бы спросить, есть ли у «merge_asof» возможность подсчитывать общее количество совпадений?

ThanksForHelping 31.10.2018 07:21

@ThanksForHelping - К сожалению, нет.

jezrael 02.11.2018 08:36

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