平滑不规则采样时间d

2024-09-24 00:31:08 发布

您现在位置:Python中文网/ 问答频道 /正文

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

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 
    ...

如您所见,测量是在不规则的时间点采样的。我需要在每次测量之前平均读数100秒(在Python中)来平滑数据。由于数据表非常庞大,因此基于迭代器的方法确实是首选。 不幸的是,经过两个小时的编码,我无法找到高效而优雅的解决方案。在

有人能帮我吗?在

编辑

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

  2. 大型~1e6-10e6管线+需要使用紧压闸板

  3. 数据近似随机游走

  4. 数据已排序

分辨率

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

^{pr2}$

谢谢大家的帮助。在


Tags: 数据方法版本编辑编码时间解决方案表格
3条回答

你的数据似乎大致是线性的:

Plot of your data http://rix0r.nl/~rix0r/share/shot-20090621.144851.gif

你想要什么样的平滑度?一条直线与此数据集的最小二乘拟合?某种低通滤波器?还是别的什么?在

请告诉我们申请表,以便我们能给你更好的建议。在

编辑:例如,根据应用程序的不同,在第一个点和最后一个点之间插入一条直线就足够了。在

你还没说清楚什么时候需要产出。我假设每个原始读数都需要一个平滑读数,平滑读数是原始读数和前100(delta)秒中任何其他读数的算术平均值。在

简单回答:使用收藏.deque... 它的读数永远不会超过“delta”秒。我设置它的方式,你可以把deque当作一个列表来处理,并且很容易计算出平均值或者一些给最近的读数增加权重的奇特的小发明。在

长话短说:

>>> the_data = [tuple(map(float, x.split())) for x in """\
... 6       0.738158581
... 21      0.801697222
[snip]
... 251     8.76853608
... 278     9.092367123""".splitlines()]
>>> import collections
>>> delta = 100.0
>>> q = collections.deque()
>>> for t, v in the_data:
...     while q and q[0][0] <= t - delta:
...         # jettison outdated readings
...         _unused = q.popleft()
...     q.append((t, v))
...     count = len(q)
...     print t, sum(item[1] for item in q) / count, count
...
...
6.0 0.738158581 1
21.0 0.7699279015 2
39.0 1.112360133 3
49.0 1.52907127225 4
54.0 1.791208525 5
79.0 2.13137915133 6
91.0 2.49500989771 7
97.0 2.8309395405 8
100.0 3.12993279856 9
118.0 3.74976297144 9
131.0 4.41385300278 9
147.0 4.99420529389 9
157.0 5.8325615685 8
176.0 6.033109419 9
202.0 7.15545189083 6
223.0 7.4342562845 6
251.0 7.9150342134 5
278.0 8.4246097095 4
>>>

编辑

一站式服务:在这里买你的小玩意儿。代码如下:

^{pr2}$

其中upsilon应该略小于1.0(<;=0是非法的,略高于零几乎不会进行平滑处理,可以得到算术平均值加上浪费的CPU时间,大于1则表示目的相反)。在

我用的是一个求和结果,加上新成员,减去旧成员。然而,在这种情况下,一个人可能会遭受累积的浮点误差。在

因此,我用一个列表实现了一个“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)

相关问题 更多 >