сглаживание нерегулярно выбранных данных времени

Модуль VB.NET является статическим классом. Компилятор обрабатывает это для вас. Каждый метод и свойство на нем есть static (Shared).

Класс со статическим (Shared) членом является именно таким: класс со статическим (Shared) членом. Вам не нужно создавать его экземпляр для доступа к статическому (Shared) методу, но вам нужно получить доступ к любому из его экземпляров.

Вы также можете определить Sub New() в модуле, и он станет статическим конструктором для модуля. При первой попытке вызвать элемент в модуле будет вызван статический конструктор для инициализации статического класса.

6
задан Boris Gorelik 22 June 2009 в 12:21
поделиться

8 ответов

Я использую результат суммы, к которому я добавляю новые члены и вычитаю старые. Однако таким образом можно страдать от накопления неточностей с плавающей запятой.

Поэтому я реализую "Deque" со списком. И всякий раз, когда мой 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)
3
ответ дан 17 December 2019 в 20:34
поделиться

Вы не сказали точно, когда вы хотите вывода. Я предполагаю, что вам нужно одно сглаженное показание для каждого необработанного показания, а сглаженное показание должно быть средним арифметическим необработанного считывания и любых других значений за предыдущие 100 (дельта) секунд.

Краткий ответ: используйте коллекции .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
>>>

Изменить

Один- остановить магазин: достань здесь свою причудливую штуковину. Вот код:

numerator = sum(item[1] * upsilon ** (t - item[0]) for item in q)
denominator = sum(upsilon ** (t - item[0]) for item in q)
gizmoid = numerator / denominator

где ипсилон должен быть немного меньше 1.0 (<= ноль недопустим, чуть выше нуля мало сглаживает, один дает вам среднее арифметическое плюс потраченное впустую время процессора, а больше единицы дает обратное цель).

2
ответ дан 17 December 2019 в 20:34
поделиться

Ваши данные кажутся примерно линейными:

График ваших данных http://rix0r.nl/~rix0r/share/shot-20090621.144851.gif

Какой вид сглаживания вы ищете? Подгонка линии к этому набору данных методом наименьших квадратов? Какой-то фильтр нижних частот? Или что-то еще?

Сообщите нам приложение, чтобы мы могли посоветовать вам немного лучше.

РЕДАКТИРОВАТЬ: Например, в зависимости от приложения интерполяция линии между первой и последней точкой может быть достаточно хорошей для ваших целей. .

0
ответ дан 17 December 2019 в 20:34
поделиться

Этот делает его линейным:

def process_data(datafile):
    previous_n = 0
    previous_t = 0
    for line in datafile:
        t, number = line.strip().split()
        t = int(t)
        number = float(number)
        delta_n = number - previous_n
        delta_t = t - previous_t
        n_per_t = delta_n / delta_t
        for t0 in xrange(delta_t):
            yield previous_t + t0, previous_n + (n_per_t * t0)
        previous_n = n
        previous_t = t

f = open('datafile.dat')

for sample in process_data(f):
    print sample
0
ответ дан 17 December 2019 в 20:34
поделиться

O (1) память на случай, если вы можете повторить ввод более одного раза - вы можете использовать один итератор для «левого» и один для «правого».

def getAvgValues(makeIter, avgSampleTime):
  leftIter = makeIter()
  leftT, leftV = leftIter.next()
  tot = 0
  count = 0
  for rightT, rightV in makeIter():
    tot += rightV
    count += 1
    while leftT <= rightT - avgSampleTime:
      tot -= leftV
      count -= 1
      leftT, leftV = leftIter.next()
    yield rightT, tot / count
0
ответ дан 17 December 2019 в 20:34
поделиться

как насчет этого, продолжайте сохранять значения до тех пор, пока разница во времени с последним временем не станет> 100, среднее значение и выдаст такие значения например

def getAvgValues(data):
    lastTime = 0
    prevValues = []
    avgSampleTime=100

    for t, v in data:
        if t - lastTime < avgSampleTime:
            prevValues.append(v)
        else:
            avgV = sum(prevValues)/len(prevValues)
            lastTime = t
            prevValues = [v]
            yield (t,avgV)

for v in getAvgValues(data):
    print v
-1
ответ дан 17 December 2019 в 20:34
поделиться

Похоже, вам нужна простая формула округления. Чтобы округлить любое число до произвольного интервала:

раунд (число / интервал) * интервал

Вы можете заменить раунд на пол или потолок вместо «ведущих до» или «поскольку» влияет. Он может работать на любом языке, включая SQL.

-2
ответ дан 17 December 2019 в 20:34
поделиться

Пока он дает экспоненциально убывающее среднее, а не общее среднее, Думаю, вам может понадобиться то, что я назвал экспоненциальной скользящей средней с изменяющейся альфой , которая на самом деле является однополюсным фильтром нижних частот. Теперь есть решение этого вопроса, и оно выполняется во времени линейно в зависимости от количества точек данных. Посмотрите, сработает ли это для вас.

0
ответ дан 17 December 2019 в 20:34
поделиться
Другие вопросы по тегам:

Похожие вопросы: