У меня есть серия измерений, которые имеют временную печать и нерегулярно разнесены. Значения в этих рядах всегда представляют собой изменения измерения - т.е. Без изменения никакого нового значения. Простой пример такой серии:
23:00:00.100 10
23:00:01.200 8
23:00:01.600 0
23:00:06.300 4
То, что я хочу достичь, - это равномерно распределенная серия взвешенных по времени средних значений. Для данного примера я мог бы стремиться к частоте, основанной на секундах, и, следовательно, иметь следующий результат:
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 )
Я ищу библиотеку Python, которая решает эту проблему. Для меня это кажется стандартной проблемой, но до сих пор я не мог найти такую функциональность в стандартных библиотеках, таких как pandas.
Алгоритм должен учитывать две вещи:
- взвешенное по времени усреднение
- учитывая значения перед текущим интервалом (и, возможно, даже впереди свинца) при формировании среднего значения
Использование pandas
data.resample('S', fill_method='pad') # forming a series of seconds
выполняет части работы. Предоставление пользовательской функции для агрегирования позволит формировать средневзвешенные средние значения, но поскольку начало интервала игнорируется, это среднее значение также будет неверным. Хуже того: дырки в серии заполняются средними значениями, ведущими в примере сверху, чтобы значения секунд 3, 4 и 5 были отличными от нуля.
data = data.resample('L', fill_method='pad') # forming a series of milliseconds
data.resample('S')
делает трюк с определенной точностью, но есть - в зависимости от точности - очень дорого. В моем случае, слишком дорого.
Изменить: решение
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)