使用Pandas扩展时间序列事件

时间:2017-08-21 12:49:29

标签: python performance pandas numpy logfile-analysis

问题

我正在寻找有关如何使这种更加pythonic和提高效率的建议。

我有一个包含事件的数据框,每个事件至少包含一个开始和结束时间戳。我正在扩展记录数,以便新表每隔一小时重叠一个记录。

这与QlikView中的IntervalMatch function基本相同。

实施例: 18:00-20:00的活动扩展为两个不同的记录,一个是18:00-19:00,另一个是19:00-20:00。

当前解决方案

我有一个完全可行的解决方案,但我认为它相当丑陋,而且在大于100k行和10-20列的大型数据集上速度相当慢。

import pandas as pd
from datetime import timedelta

def interval_match(df):

    intervals = []

    def perdelta(start, end, delta):
        curr = start.replace(minute=0, second=0)
        while curr < end:
            yield curr
            curr += delta

    def interval_split(x):

        for t in perdelta(x.Start, x.End, timedelta(hours=1)):
            _ = ([x.id,
                  x.Start,
                  x.End,
                  max(t, x.Start),
                  min((t+timedelta(hours=1), x.End))])

            intervals.append(_)

    df.apply(interval_split, axis=1)

    ndf = pd.DataFrame(intervals, 
                       columns=['id', 
                                'Start', 
                                'End', 
                                'intervalStart', 
                                'intervalEnd'])

    ndf['Duration'] = ndf.iEnd - ndf.iStart

    return ndf

对于一些示例数据,函数interval_match()可以像这样使用:

# Some example data
df = pd.DataFrame({'End': {0: pd.Timestamp('2016-01-01 09:24:20')},
                   'Start': {0: pd.Timestamp('2016-01-01 06:56:10')},
                   'id': {0: 1234562}})


# Running the function
interval_match(df).to_dict()


# Output
{'Duration': {0: Timedelta('0 days 00:03:50'),
              1: Timedelta('0 days 01:00:00'),
              2: Timedelta('0 days 01:00:00'),
              3: Timedelta('0 days 00:24:20')},
      'End': {0: Timestamp('2016-01-01 09:24:20'),
              1: Timestamp('2016-01-01 09:24:20'),
              2: Timestamp('2016-01-01 09:24:20'),
              3: Timestamp('2016-01-01 09:24:20')},
    'Start': {0: Timestamp('2016-01-01 06:56:10'),
              1: Timestamp('2016-01-01 06:56:10'),
              2: Timestamp('2016-01-01 06:56:10'),
              3: Timestamp('2016-01-01 06:56:10')},
'intervalEnd':{0: Timestamp('2016-01-01 07:00:00'),
              1: Timestamp('2016-01-01 08:00:00'),
              2: Timestamp('2016-01-01 09:00:00'),
              3: Timestamp('2016-01-01 09:24:20')},
'intervalStart': {0: Timestamp('2016-01-01 06:56:10'),
              1: Timestamp('2016-01-01 07:00:00'),
              2: Timestamp('2016-01-01 08:00:00'),
              3: Timestamp('2016-01-01 09:00:00')},
       'id': {0: 1234562, 
              1: 1234562, 
              2: 1234562, 
              3: 1234562}}

我的愿望是

  1. 提高效率,最好使用内置的Pandas功能或一些神奇的魔法。
  2. 不必像今天在interval_split函数中那样处理列。只需操作,然后展开整个数据框。
  3. 对任何建议或帮助的赞赏。

1 个答案:

答案 0 :(得分:1)

我做了一个变体(受您的代码启发),并且运行非常缓慢。我花了大约5分钟的时间来处理2万行数据,分析后的罪魁祸首是.append。有一个技巧可以将所有记录放入字典中,然后使用DataFrame的{​​{1}}方法。使用from_dict进行相同的20k行,它在大约5秒钟内完成(因此快了约60倍)。

我已附加了受您启发的代码,它对于列输入也是通用的(我的测试使用与生产使用是不同的)。

from_dict