有哪些方法可以合并时间戳不完全匹配的列?
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
我可以在[‘date’,’employee_id’,’session_id’]加入,但是有时同一名员工在同一日期会有多个相同的会话,这会导致重复。我可以删除发生这种情况的行,但是如果这样做,我将丢失有效的会话。
如果DF1的时间戳小于DF2的时间戳少于5分钟,并且session_id和employee_id也匹配,是否有一种有效的加入方法?如果存在匹配的记录,则时间戳将总是比DF1稍晚,因为某个事件在某个将来的时间点触发。
['employee_id', 'session_id', 'timestamp<5minutes']
编辑 -我认为以前可能有人遇到过此问题。
我正在考虑这样做:
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)
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
interval_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]视为单独的会话。
df2[0:3]
df1[0:3]
df1[3]
df2[3]
这实质上就是您在编辑中建议的内容。您希望将两个表中的时间戳映射到以时间戳为中心的10分钟间隔,并四舍五入到最接近的5分钟。
每个间隔都可以由其中点唯一表示,因此您可以合并时间戳上的数据帧,四舍五入到最接近的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
请注意,这并不完全正确。会话df1[2]和和df2[2],尽管相距仅3分钟,却不被视为重复。这是因为它们位于间隔边界的不同侧。
df1[2]
df2[2]
这是另一种方法,取决于in中的会话在中df1具有零或一个重复项的条件df2。
df1
df2
我们将时间戳替换df1为最近的时间戳,df2其中匹配的时间为employee_id,session_id 并且 相距不到5分钟。
employee_id
session_id
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。我写的内容可能可以进一步优化,但是在大型数据集上仍然需要很长时间。