当前位置: 首页 > 面试题库 >

根据时间戳合并的pandas 不完全匹配

齐献
2023-03-14
问题内容

有哪些方法可以合并时间戳不完全匹配的列?

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']

编辑 -我认为以前可能有人遇到过此问题。

我正在考虑这样做:

  1. 在每个数据帧上加上我的时间戳
  2. 创建一个时间戳+ 5分钟(四舍五入)的列
  3. 创建一个作为时间戳的列-5分钟(四舍五入)
  4. 创建一个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

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]视为单独的会话。

解决方案1:间隔匹配

这实质上就是您在编辑中建议的内容。您希望将两个表中的时间戳映射到以时间戳为中心的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分钟,却不被视为重复。这是因为它们位于间隔边界的不同侧。

解决方案2:一对一匹配

这是另一种方法,取决于in中的会话在中df1具有零或一个重复项的条件df2

我们将时间戳替换df1为最近的时间戳,df2其中匹配的时间为employee_idsession_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。我写的内容可能可以进一步优化,但是在大型数据集上仍然需要很长时间。



 类似资料:
  • 有两个这样的数据帧(示例) df1 df2 然后,我想加入df1和df2,但是我不知道如何做到这一点,因为在第二个df中我只有开始和结束时间。如何根据第二个df的数据将条件放在第一个df上? 这就是我想要的

  • 问题内容: 如何从MongoDB集合中的时间(HH:MM:SS.Milisecond)值大于零的日期字段中选择记录,并通过保持日期的时间(HH:MM:SS)值为零来更新记录值是否与Python脚本中的现有值相同? 当前数据如下所示- 如何在Python脚本中仅选择第4、5、6和7行,并使用时间戳将其更新为零? 更新后,数据如下所示- 问题答案: 最好的方式来更新您的文件,并在时间使用日期时间模块,

  • 我想在指定的时间戳范围内从数据帧中选择行的子集。 下面是我所做的,但它似乎没有工作。我正在尝试选择发生在01/01/2019 01:00和01/01/2021 01:00之间的行子集。 非常感谢。

  • 说明 pika新版binlog有时间戳,开发binlog_sender工具,根据输入的时间段回放对应数据到某个pika实例 工具目录: pika/tools/binlog_tools/binlog_sender 使用参数: -h -- 显示帮助 -t -- l 显示日志类型,old 或new -i -- pika实例的ip -p -- pika实例的port -n -- 输入的binlog的路径

  • 问题内容: 我将csv文件读入pandas数据框,得到以下信息: 无论是和列有100个元素。我想将Hour的相应元素添加到TDate。 我尝试了以下方法: 但是我得到了错误,因为td似乎没有将array作为参数。如何将的每个元素添加到的相应元素中。 问题答案: 我想你可以添加到列列转换有:

  • 问题内容: 场景: 我有一个从Excel工作表中检索到具有多个列的数据框。其中一些列是日期:一些仅包含日期(yyyy:mm:dd),一些具有日期和时间戳(yyyy:mm:dd 00.00.000000)。 问题: 当日期不是数据框的索引时,如何从日期中删除时间戳? 我已经尝试了什么: 在SO的其他文章中使用pandas中的日期- 在datetime中删除看不见的字符并转换为字符串以及如何剥离pan