哪些方法可用于合并时间戳不完全匹配的列?
DF1:
date start_time employee_id session_id
01/01/2016 01/01/2016 06:03:13 7261824 871631182
DF2:
date start_time employee_id session_id
01/01/2016 01/01/2016 06:03:37 7261824 871631182
我可以在“日期”、“员工ID”、“会话ID”上加入,但有时同一员工会在同一日期有多个相同的会话,这会导致重复。我可以删除发生这种情况的行,但如果这样做,将丢失有效的会话。
如果df1的时间戳与df2的时间戳之间的时间戳小于5分钟,并且会话ID和雇员ID也匹配,那么是否有一种有效的加入方法?如果有匹配的记录,那么时间戳总是稍迟于df1,因为某个事件是在将来某个点触发的。
['employee_id', 'session_id', 'timestamp<5minutes']
编辑-我假设以前有人会遇到这个问题。
我想这样做:
在每个数据帧上记录我的时间戳
创建时间戳为+5分钟(四舍五入)的列
创建时间戳为-5分钟(四舍五入)的列
创建一个10分钟的间隔字符串来联接上的文件
df1['low_time'] = df1['start_time'] - timedelta(minutes=5)
df1['high_time'] = df1['start_time'] + timedelta(minutes=5)
df1['interval_string'] = df1['low_time'].astype(str) + df1['high_time'].astype(str)
有人知道如何将这5分钟的间隔四舍五入到最接近的5分钟标记吗?
02:59:37-5分钟=02:55:00
02:59:37+5分钟=03:05:00
间隔_string='02:55:00-03:05:00'
pd.merge(df1, df2, how = 'left', on = ['employee_id', 'session_id', 'date', 'interval_string']
有人知道怎么这样打发时间吗?这似乎可行。您仍然根据日期、员工和会话进行匹配,然后查找基本上在相同10分钟间隔或范围内的时间
最佳答案
请考虑以下问题的迷你版本:
from io import StringIO
from pandas import read_csv, to_datetime
# how close do sessions have to be to be considered equal? (in minutes)
threshold = 5
# datetime column (combination of date + start_time)
dtc = [['date', 'start_time']]
# index column (above combination)
ixc = 'date_start_time'
df1 = read_csv(StringIO(u'''
date,start_time,employee_id,session_id
01/01/2016,02:03:00,7261824,871631182
01/01/2016,06:03:00,7261824,871631183
01/01/2016,11:01:00,7261824,871631184
01/01/2016,14:01:00,7261824,871631185
'''), parse_dates=dtc)
df2 = read_csv(StringIO(u'''
date,start_time,employee_id,session_id
01/01/2016,02:03:00,7261824,871631182
01/01/2016,06:05:00,7261824,871631183
01/01/2016,11:04:00,7261824,871631184
01/01/2016,14:10:00,7261824,871631185
'''), parse_dates=dtc)
哪个给了
>>> df1
date_start_time employee_id session_id
0 2016-01-01 02:03:00 7261824 871631182
1 2016-01-01 06:03:00 7261824 871631183
2 2016-01-01 11:01:00 7261824 871631184
3 2016-01-01 14:01:00 7261824 871631185
>>> df2
date_start_time employee_id session_id
0 2016-01-01 02:03:00 7261824 871631182
1 2016-01-01 06:05:00 7261824 871631183
2 2016-01-01 11:04:00 7261824 871631184
3 2016-01-01 14:10:00 7261824 871631185
您希望在合并时将
df2[0:3]
视为df1[0:3]
的重复项(因为它们的间隔分别小于5分钟),但将df1[3]
和df2[3]
视为单独的会话。解决方案1:间隔匹配
这基本上就是你在编辑中的建议。您希望将两个表中的时间戳映射到以四舍五入到最近5分钟的时间戳为中心的10分钟间隔。
每个间隔可以用其中点唯一地表示,因此您可以合并时间戳上的数据帧,并四舍五入到最接近的5分钟。例如:
import numpy as np
# half-threshold in nanoseconds
threshold_ns = threshold * 60 * 1e9
# compute "interval" to which each session belongs
df1['interval'] = to_datetime(np.round(df1.date_start_time.astype(np.int64) / threshold_ns) * threshold_ns)
df2['interval'] = to_datetime(np.round(df2.date_start_time.astype(np.int64) / threshold_ns) * threshold_ns)
# join
cols = ['interval', 'employee_id', 'session_id']
print df1.merge(df2, on=cols, how='outer')[cols]
哪个指纹
interval employee_id session_id
0 2016-01-01 02:05:00 7261824 871631182
1 2016-01-01 06:05:00 7261824 871631183
2 2016-01-01 11:00:00 7261824 871631184
3 2016-01-01 14:00:00 7261824 871631185
4 2016-01-01 11:05:00 7261824 871631184
5 2016-01-01 14:10:00 7261824 871631185
请注意,这并不完全正确。尽管间隔只有3分钟,但会话
df1[2]
和df2[2]
不被视为重复会话。这是因为它们在间隔边界的不同边上。解决方案2:一对一匹配
这是另一种方法,它取决于
df1
中的会话在df2
中有零个或一个重复项的条件。我们将
df1
中的时间戳替换为df2
中最接近的时间戳,该时间戳与employee_id
和session_id
中的时间戳匹配,并且距离小于5分钟。from datetime import timedelta
# get closest match from "df2" to row from "df1" (as long as it's below the threshold)
def closest(row):
matches = df2.loc[(df2.employee_id == row.employee_id) &
(df2.session_id == row.session_id)]
deltas = matches.date_start_time - row.date_start_time
deltas = deltas.loc[deltas <= timedelta(minutes=threshold)]
try:
return matches.loc[deltas.idxmin()]
except ValueError: # no items
return row
# replace timestamps in "df1" with closest timestamps in "df2"
df1 = df1.apply(closest, axis=1)
# join
cols = ['date_start_time', 'employee_id', 'session_id']
print df1.merge(df2, on=cols, how='outer')[cols]
哪个指纹
date_start_time employee_id session_id
0 2016-01-01 02:03:00 7261824 871631182
1 2016-01-01 06:05:00 7261824 871631183
2 2016-01-01 11:04:00 7261824 871631184
3 2016-01-01 14:01:00 7261824 871631185
4 2016-01-01 14:10:00 7261824 871631185
这种方法明显较慢,因为您必须搜索
df2
中每行的整个df1
。我所写的可能会进一步优化,但在大型数据集上仍然需要很长时间。关于python - 基于时间戳不完全匹配的pandas合并,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/34880539/