【问题标题】:pandas aggregation based on timestamp threshold基于时间戳阈值的 pandas 聚合
【发布时间】:2021-10-04 05:56:17
【问题描述】:

希望有人能帮我解决这个问题。

我有一个结构如下的 csv 文件:

如果事件从匹配的第一个事件开始以 10 分钟的阈值出现,我正在尝试根据 messagenameuserID 对事件进行分组。

我期望从 csv 得到的输出是只看到 3 行,因为第二行和第三行(因为它们在 10 分钟的阈值内并且消息、名称和 ID 相同,它们应该被分组)并且有一个额外的列名称 event_count 报告该事件发生了多少次。像这样

我开始处理这个问题,我的脚本如下所示:

import csv
import pandas as pd

# 0. sort data by timestamp if not already sorted
file_csv = 'test.csv'
f = pd.read_csv(file_csv)
f['@timestamp'] = pd.to_datetime(f['@timestamp'])
f = f.sort_values('@timestamp')

# lazy groupby
groups = f.groupby(['message','name','userID'])

# 1. compute the time differences `timediff` and compare to threshold
f['timediff'] = groups['@timestamp'].diff() < pd.Timedelta(minutes=10)

# 2. find the blocks with cumsum
f['event_count'] = groups['timediff'].cumsum()

# 3. groupby the blocks
out = (f.groupby(['message','name', 'userID'])
       .agg({'@timestamp':'first', 'timediff':'count'})
       )



keep_col = ['@timestamp', 'message', 'name', 'userID', 'event_count']
new_f = f[keep_col]
new_f.to_csv("aggregationtest.csv", index=False)

但是聚合是完全错误的,因为即使它们没有落在 10 分钟的阈值内,也会将所有事件分组在一起。

如果有人可以帮助我理解问题,我真的很难理解我做错了什么

更新:

经过一些测试,我设法得到了更接近我期望的输出,但仍然是错误的。

我对 out 变量做了一些更新,如下所示

out = (f.groupby(['message','name', 'userID', 'timediff']).agg({'@timestamp':'first','message': 'unique','name': 'unique', 'userID': 'unique', 'timediff': 'count'}))

这段代码现在产生如下输出:

但即使它现在分组,计数也是错误的。拥有这个 csv 文件

@timestamp,message,name,userID
2021-07-13 21:36:18,Failed to download file,Failed to download file,admin
2021-07-14 03:46:16,Successful Logon for user "user1",Logon Attempt,1
2021-07-14 03:51:16,Successful Logon for user "user1",Logon Attempt,1
2021-07-14 03:54:16,Successful Logon for user "user1",Logon Attempt,1
2021-07-14 04:55:16,Successful Logon for user "user1",Logon Attempt,1

我希望有以下 event_count

1
3
1

但我变得不一样了。

【问题讨论】:

  • 请以纯文本形式发布您的 csv 文件样本,以便我们重现您的问题。
  • 非常感谢您的回复。我用纯文本的 csv 更新了我的帖子。再次感谢您

标签: python-3.x pandas dataframe csv


【解决方案1】:

您必须以某种方式确定组内的不同时期。下面的解决方案为组内的每个句点命名,然后可以将其包含在生成计数的groupby 中:

import pandas as pd

file_csv = 'test.csv'
f = pd.read_csv(file_csv)
f['@timestamp'] = pd.to_datetime(f['@timestamp'])
f = f.sort_values('@timestamp')

def check(item): #taken from https://stackoverflow.com/a/53189777/11380795
    diffs = item - item.shift()
    laps = diffs > pd.Timedelta('10 min')
    periods = laps.cumsum().apply(lambda x: 'period_{}'.format(x+1))
    return periods

#create period names 
f['period'] = f.groupby(['message','name','userID'])['@timestamp'].transform(check)
#groupby and count
(f.groupby(['message','name', 'userID', 'period']).agg({'@timestamp':'first', 'period': 'count'})).rename(columns={"period": "timediff"}).reset_index()

输出:

message name userID period @timestamp timediff
0 Failed to download file Failed to download file admin period_1 2021-07-13 21:36:18 1
1 Successful Logon for user "user1" Logon Attempt 1 period_1 2021-07-14 03:46:16 3
2 Successful Logon for user "user1" Logon Attempt 1 period_2 2021-07-14 04:55:16 1

【讨论】:

  • 你是绝对的传奇,我的朋友。你刚刚帮我解决了一个我已经工作了 2 天的问题。谢谢谢谢谢谢谢谢谢谢谢谢谢谢
猜你喜欢
  • 2020-02-18
  • 1970-01-01
  • 2016-10-09
  • 1970-01-01
  • 1970-01-01
  • 2019-02-25
  • 2016-09-24
  • 1970-01-01
  • 2016-04-25
相关资源
最近更新 更多