pandas 数据框:基于列和时间范围的重复项

6

我有一个(在这里非常简化的)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个回答

7
这段代码可以得到预期的输出。
df[(df.groupby(["msg"], as_index=False)["datetime"].diff().fillna(0).dt.seconds <= 3).reset_index(drop=True)]

我已经按数据框的 "msg" 列进行了分组,然后选择了该数据框的 "datetime" 列,并使用内置函数 diff。 Diff 函数找到该列值之间的差异。用零填充 NaT 值,并仅选择那些具有小于 3 秒的值的索引。
在使用上述代码之前,请确保您的数据框按升序排列 datetime。

如果我的回答对你有帮助,请不要忘记接受它。谢谢! - Akshay Kandul
是的,已经接受了,非常感谢您的帮助(对于延迟感到抱歉)!它做到了我需要的。 - dliv
1
@dliv 感谢您点赞这个答案。很高兴我能帮到您。请检查此链接以接受答案。 - Akshay Kandul
现在需要用fillna(pd.Timedelta(seconds=0))替换fillna(0) - Molly Zhou

1
这段代码适用于你的示例数据,但你可能需要尝试一些极端情况。
从你的问题中我假设你想过滤掉第一次在df中出现的消息。如果你有想要保留字符串在另一个阈值之后再次出现的实例,那么它将不起作用。
简而言之,我编写了一个函数,它将使用你的数据框和“msg”进行过滤。它获取消息首次出现的时间戳并将其与所有其他出现的时间进行比较。
然后,它仅选择在首次出现后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])

非常感谢你的帮助,Tkanno!你的建议也很有帮助! - dliv

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接