温馨提示:本文翻译自stackoverflow.com,查看原文请点击:python - Aggregating events. Reducing df size. In search of more elegant way
pandas python

python - 汇总事件。

发布于 2020-03-27 15:56:55

我有一个具有下一个结构的时间序列数据帧:

Loc | Event |       Start        |         End       |  
 A  |  aaa  |2018-08-30 00:26:29 |2018-08-30 00:26:59|  
 A  |  aaa  |2018-08-30 00:26:30 |2018-08-30 00:26:47|  
 A  |  aaa  |2018-08-30 00:38:05 |2018-08-30 00:39:09|  
 A  |  aaa  |2018-08-30 00:40:31 |2018-08-30 00:40:41|  
 A  |  aaa  |2018-08-30 00:57:17 |2018-08-30 00:57:28|
 A  |  aaa  |2018-08-30 00:57:36 |2018-08-30 00:58:07|  
 A  |  aaa  |2018-08-30 00:57:53 |2018-08-30 00:59:23|  
 A  |  aaa  |2018-08-30 00:57:58 |2018-08-30 00:58:11|  
 A  |  aaa  |2018-08-30 00:58:00 |2018-08-30 00:58:08|  
 A  |  aaa  |2018-08-30 01:27:58 |2018-08-30 01:28:58|  

我的目标是根据事件之间的间隔将一组事件汇总为一个事件。从上面的示例中可以看到,有许多记录持续几秒钟,并且也在几秒钟之内生成。此类事件必须合并为一个,以组中第一个事件的开始时间和组中最后一个事件的最后时间为准。

在此处输入图片说明

结果,必须实现下一个输出:

Loc | Event |       Start        |         End       |  
 A  |  aaa  |2018-08-30 00:26:29 |2018-08-30 00:26:59|  
 A  |  aaa  |2018-08-30 00:26:30 |2018-08-30 00:26:47|  
 A  |  aaa  |2018-08-30 00:38:05 |2018-08-30 00:39:09|  
 A  |  aaa  |2018-08-30 00:40:31 |2018-08-30 00:40:41|  
 A  |  aaa  |2018-08-30 00:57:17 |2018-08-30 00:58:08|
 A  |  aaa  |2018-08-30 01:27:58 |2018-08-30 01:28:58|  

现在,我设法通过许多其他变量和for循环实现了这一目标,而且速度相当慢。因此,任何关于如何使用 pandas 方法实现此目标的想法都非常受欢迎。

查看更多

查看更多

提问者
Ison
被浏览
13
Zaraki Kenpachi 2020-01-31 17:37

要解决此问题,您需要:

  1. 创建while循环以遍历每个日期时间范围
  2. 使用新的日期时间范围对df进行切片
  3. 从切片df获取结果
  4. 计算while循环的新输出变量
  5. 将具有结果的df收集到列表中,然后合并它们

您可以在这里(代码中的一些注释):

import pandas as pd
from io import StringIO
from dateutil.relativedelta import relativedelta


data = StringIO("""
Loc|Event|Start|End
A|aaa|2018-08-30 00:26:29|2018-08-30 00:26:59
A|aaa|2018-08-30 00:26:30|2018-08-30 00:26:47
A|aaa|2018-08-30 00:38:05|2018-08-30 00:39:09
A|aaa|2018-08-30 00:40:31|2018-08-30 00:40:41
A|aaa|2018-08-30 00:57:17|2018-08-30 00:57:28
A|aaa|2018-08-30 00:57:36|2018-08-30 00:58:07
A|aaa|2018-08-30 00:57:53|2018-08-30 00:59:23
A|aaa|2018-08-30 00:57:58|2018-08-30 00:58:11
A|aaa|2018-08-30 00:58:00|2018-08-30 00:58:08
A|aaa|2018-08-30 01:27:58|2018-08-30 01:28:58
""")

# load data into data frame
df = pd.read_csv(data, sep='|')

# convert string to datetime
df['Start'] = pd.to_datetime(df['Start'])
df['End'] = pd.to_datetime(df['End'])


def get_result(df_filtered):
    df2 = pd.DataFrame({'Loc':df_filtered['Loc'].unique(), 'Event':df_filtered['Event'].unique(), 'Start':df_filtered['Start'].min(), 'End':df_filtered['End'].max()})
    start_end = df_filtered['Start'].max()

    return df2, start_end


# get datetime group range
min_datetime = df['Start'].min()
max_datetime = min_datetime + relativedelta(minutes=6)
# define variables for while loop
end_end = df['Start'].max()
start_end = min_datetime

results_list = []
while end_end > start_end:
    # filter rows by dates
    df_filtered = df[(df['Start'] >= min_datetime) & (df['End'] < max_datetime)]
    # get result and new start datetime
    df2, start_end = get_result(df_filtered)
    # get new values for max and min datetime
    df_start = df[df['Start'] > start_end]
    min_datetime = df_start['Start'].min()
    max_datetime = min_datetime + relativedelta(minutes=6)
    # append df with results
    results_list.append(df2)


df = pd.concat(results_list)

输出:

  Loc Event               Start                 End
0   A   aaa 2018-08-30 00:26:29 2018-08-30 00:26:59
0   A   aaa 2018-08-30 00:38:05 2018-08-30 00:40:41
0   A   aaa 2018-08-30 00:57:17 2018-08-30 00:59:23
0   A   aaa 2018-08-30 01:27:58 2018-08-30 01:28:58