pandas dataframe:基于列和时间范围的重复项

时间:2017-06-27 09:45:00

标签: python pandas datetime duplicates conditional-statements

我有一个(非常简单的)pandas数据框,如下所示:

df

    datetime             user   type   msg
0  2012-11-11 15:41:08   u1     txt    hello world
1  2012-11-11 15:41:11   u2     txt    hello world
2  2012-11-21 17:00:08   u3     txt    hello world
3  2012-11-22 18:08:35   u4     txt      hello you
4  2012-11-22 18:08:37   u5     txt      hello you

我现在要做的是获取所有重复的消息,这些消息的时间戳在3秒内。所需的输出是:

   datetime              user   type   msg
0  2012-11-11 15:41:08   u1     txt    hello world
1  2012-11-11 15:41:11   u2     txt    hello world
3  2012-11-22 18:08:35   u4     txt      hello you
4  2012-11-22 18:08:37   u5     txt      hello you

没有第三行,因为它的文本与第一行和第二行相同,但它的时间戳不是 在3秒的范围内。

我尝试将列datetime和msg定义为duplicate()方法的参数,但它返回一个空数据帧,因为时间戳不相同:

mask = df.duplicated(subset=['datetime', 'msg'], keep=False)

print(df[mask])
Empty DataFrame
Columns: [datetime, user, type, msg, MD5]
Index: []

有没有办法为我的“datetime”参数定义范围?为了说明,有些东西 像:

mask = df.duplicated(subset=['datetime_between_3_seconds', 'msg'], keep=False)

这里的任何帮助都会非常感激。

2 个答案:

答案 0 :(得分:4)

这段代码给出了预期的输出

df[(df.groupby(["msg"], as_index=False)["datetime"].diff().fillna(0).dt.seconds <= 3).reset_index(drop=True)]

我已经分组了&#34; msg&#34;数据帧的列,然后选择&#34; datetime&#34;该数据帧的列,并在内置函数diff中使用。 Diff函数查找该列的值之间的差异。将NaT值填充为零,仅选择值小于3秒的索引。

在使用上述代码之前,请确保您的数据框按日期时间按升序排序。

答案 1 :(得分:1)

这段代码适用于您的示例数据,尽管您可能需要处理任何极端情况。

根据您的问题,我假设您要在第一次出现在df中时过滤掉消息。如果您想要保留字符串,如果它再次出现在另一个阈值之后,它将无法工作。

简而言之,我编写了一个功能,它将采用您的数据帧和&#39; msg&#39;过滤。它需要第一次显示消息的时间戳,并将其与其显示的所有其他时间进行比较。

然后仅选择第一次出现后3秒内出现的实例。

    import numpy as np
    import pandas as pd
    #function which will return dataframe containing messages within three seconds of the first message
    def get_info_within_3seconds(df, msg):
        df_of_msg = df[df['msg']==msg].sort_values(by = 'datetime')
        t1 = df_of_msg['datetime'].reset_index(drop = True)[0]
        datetime_deltas = [(i -t1).total_seconds() for i in df_of_msg['datetime']]
        filter_list = [i <= 3.0 for i in datetime_deltas]
        return df_of_msg[filter_list]

    msgs = df['msg'].unique()
    #apply function to each unique message and then create a new df 
    new_df = pd.concat([get_info_within_3seconds(df, i) for i in msgs])