平滑不规则采样的时间数据

Bor*_*lik 6 python datetime data-mining smoothing

给定一个表,其中第一列是经过某个参考点的秒数,第二列是任意测量值:

6   0.738158581
21  0.801697222
39  1.797224596
49  2.77920469
54  2.839757536
79  3.832232283
91  4.676794376
97  5.18244704
100 5.521878863
118 6.316630137
131 6.778507504
147 7.020395216
157 7.331607129
176 7.637492223
202 7.848079136
223 7.989456499
251 8.76853608
278 9.092367123 
    ...
Run Code Online (Sandbox Code Playgroud)

如您所见,在不规则的时间点对测量结果进行采样.我需要通过在每次测量之前将读数平均最多100秒来平滑数据(在Python中).由于数据表很大,因此最好使用基于迭代器的方法.不幸的是,经过两个小时的编码后,我无法找到高效优雅的解决方案.

谁能帮我?

编辑小号

  1. 我希望每个原始读数都有一个平滑的读数,平滑的读数是原始读数的算术平均值和前100(delta)秒中的任何其他读数.(约翰,你说得对)

  2. 巨大的~1e6 - 10e6线+需要使用紧RAM

  3. 数据大致是随机游走

  4. 数据已排序

解析度

我测试了J Machin和yairchu提出的解决方案.他们都给出了相同的结果,但是,在我的数据集中,J Machin的版本呈指数级,而yairchu的版本是线性的.以下是由IPython的%timeit(以微秒为单位)测量的执行时间:

data size   J Machin    yairchu
10        90.2        55.6
50          930         258
100         3080        514
500         64700       2660
1000        253000      5390
2000        952000      11500
Run Code Online (Sandbox Code Playgroud)

谢谢大家的帮助.

yai*_*chu 3

我正在使用一个求和结果,在其中添加新成员并减去旧成员。然而,通过这种方式,人们可能会遭受累积浮点误差的困扰。

因此我用列表实现了“Deque”。每当我的双端队列重新分配为更小的大小时。我在同一场合重新计算总和。

我还计算直到 x 点(包括 x 点)的平均值,因此至少有一个样本点需要平均。

def getAvgValues(data, avgSampleTime):
  lastTime = 0
  prevValsBuf = []
  prevValsStart = 0
  tot = 0
  for t, v in data:
    avgStart = t - avgSampleTime
    # remove too old values
    while prevValsStart < len(prevValsBuf):
      pt, pv = prevValsBuf[prevValsStart]
      if pt > avgStart:
        break
      tot -= pv
      prevValsStart += 1
    # add new item
    tot += v
    prevValsBuf.append((t, v))
    # yield result
    numItems = len(prevValsBuf) - prevValsStart
    yield (t, tot / numItems)
    # clean prevVals if it's time
    if prevValsStart * 2 > len(prevValsBuf):
      prevValsBuf = prevValsBuf[prevValsStart:]
      prevValsStart = 0
      # recalculate tot for not accumulating float precision error
      tot = sum(v for (t, v) in prevValsBuf)
Run Code Online (Sandbox Code Playgroud)