将不规则时间标记的测量值转换为等间隔的时间加权平均值

Tim*_*dle 15 python time-series pandas

我有一系列时间戳和不规则间距的测量.这些系列中的值始终代表测量值的变化 - 即没有变化就没有新值.这样一个系列的一个简单例子是:

23:00:00.100     10
23:00:01.200      8
23:00:01.600      0
23:00:06.300      4
Run Code Online (Sandbox Code Playgroud)

我想要达到的是一系列等间隔的时间加权平均值.对于给定的示例,我可能会瞄准基于秒的频率,因此结果如下:

23:00:01     NaN ( the first 100ms are missing )
23:00:02     5.2 ( 10*0.2 + 8*0.4 + 0*0.4 )
23:00:03       0
23:00:04       0
23:00:05       0
23:00:06     2.8 ( 0*0.3 + 4*0.7 )
Run Code Online (Sandbox Code Playgroud)

我正在寻找解决该问题的Python库.对我来说,这似乎是一个标准问题,但到目前为止我在像熊猫这样的标准库中找不到这样的功能.

该算法需要考虑两件事:

  • 时间加权平均
  • 在形成平均值时考虑当前区间之前的值(可能甚至领先于线索)

使用熊猫

data.resample('S', fill_method='pad')          # forming a series of seconds
Run Code Online (Sandbox Code Playgroud)

做部分工作.为聚合提供用户定义的函数将允许形成时间加权平均值,但由于忽略了间隔的开始,因此该平均值也将是不正确的.更糟糕的是:系列中的孔用平均值填充,在上面的示例中导致秒3,4和5的值非零.

data = data.resample('L', fill_method='pad')   # forming a series of milliseconds
data.resample('S')
Run Code Online (Sandbox Code Playgroud)

具有一定准确性的技巧,但是 - 取决于准确性 - 非常昂贵.在我的情况下,太贵了.

编辑:解决方案

import pandas as pa
import numpy as np
from datetime import datetime
from datetime import timedelta

time_stamps=[datetime(2013,04,11,23,00,00,100000), 
             datetime(2013,04,11,23,00,1,200000),
             datetime(2013,04,11,23,00,1,600000),
             datetime(2013,04,11,23,00,6,300000)]
values = [10, 8, 0, 4]
raw = pa.TimeSeries(index=time_stamps, data=values)

def round_down_to_second(dt):
    return datetime(year=dt.year, month=dt.month, day=dt.day, 
                    hour=dt.hour, minute=dt.minute, second=dt.second)

def round_up_to_second(dt):
    return round_down_to_second(dt) + timedelta(seconds=1)

def time_weighted_average(data):
    end = pa.DatetimeIndex([round_up_to_second(data.index[-1])])
    return np.average(data, weights=np.diff(data.index.append(end).asi8))

start = round_down_to_second(time_stamps[0])
end = round_down_to_second(time_stamps[-1])
range = pa.date_range(start, end, freq='S')
data = raw.reindex(raw.index + range)
data = data.ffill()

data = data.resample('S', how=time_weighted_average)
Run Code Online (Sandbox Code Playgroud)

mst*_*ger 5

您可以使用traces执行此操作。

from datetime import datetime
import traces

ts = traces.TimeSeries(data=[
    (datetime(2016, 9, 27, 23, 0, 0, 100000), 10),
    (datetime(2016, 9, 27, 23, 0, 1, 200000), 8),
    (datetime(2016, 9, 27, 23, 0, 1, 600000), 0),
    (datetime(2016, 9, 27, 23, 0, 6, 300000), 4),
])

regularized = ts.moving_average(
    start=datetime(2016, 9, 27, 23, 0, 1),
    sampling_period=1,
    placement='left',
)
Run Code Online (Sandbox Code Playgroud)

结果是:

[(datetime(2016, 9, 27, 23, 0, 1), 5.2),
 (datetime(2016, 9, 27, 23, 0, 2), 0.0),
 (datetime(2016, 9, 27, 23, 0, 3), 0.0),
 (datetime(2016, 9, 27, 23, 0, 4), 0.0),
 (datetime(2016, 9, 27, 23, 0, 5), 0.0),
 (datetime(2016, 9, 27, 23, 0, 6), 2.8)]
Run Code Online (Sandbox Code Playgroud)