2014-01-13 3 views
1

Я пытаюсь вычислить скользящее среднее, но с установленным размером шага между каждым средним. Например, если я вычисление среднего окна 4 элемента каждые 2 элементов:Среднее число перекрывающихся окон в Python

data = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] 

Это должно произвести среднее значение [1, 2, 3, 4], [3, 4, 5, 6] , [5, 6, 7, 8], [7, 8, 9, 10].

window_avg = [2.5, 4.5, 6.5, 8.5] 

Мои данные таковы, что концовка будет урезана до обработки, поэтому нет никаких проблем с длиной по отношению к размеру окна.

Я немного читал о том, как делать скользящие средние в Python, и, похоже, много использования itertools; однако итераторы идут по одному элементу за раз, и я не могу понять, как иметь размер шага между каждым вычислением среднего. (How to calculate moving average in Python 3?)

Я также был в состоянии сделать это, прежде чем в MATLAB, создав матрицу индексов, которые перекрывают, а затем индексировать вектор данных и выполнение столбца мудрого среднего (Create matrix by repeatedly overlapping a vector). Однако, поскольку этот вектор довольно большой (~ 70 000 элементов, окно из 450 выборок, среднее каждые 30 выборок), для вычисления, вероятно, потребуется слишком много памяти.

Любая помощь была бы принята с благодарностью. Я использую Python 2.7.

+0

Я бы попробовал что-то по строкам 'n = 4; s == 2; [sum (data [s * i: s * i + n])/n для i, datum в перечислении (data [:: s])] ', но, возможно, это не то, что вы ищете (' datum' здесь не нужно , но 'range (len (data))' просто выглядит так непитоновым). – Evert

ответ

1

Один из способов вычислить среднее значение скользящего окна по списку в Python - использовать понимание списка. Вы можете использовать

>>> range(0, len(data), 2) 
[0, 2, 4, 6, 8] 

, чтобы получить исходные показатели каждого окна, а затем numpy «s mean функции взять среднее значение каждого окна. Смотрите ниже демо:

>>> import numpy as np 
>>> window_size = 4 
>>> stride = 2 
>>> window_avg = [ np.mean(data[i:i+window_size]) for i in range(0, len(data), stride) 
        if i+window_size <= len(data) ] 
>>> window_avg 
[2.5, 4.5, 6.5, 8.5] 

Обратите внимание, что список понимание действительно есть условие, чтобы убедиться, что она вычисляет только среднее «полных окон», или подсписков с точно window_size элементами.

При запуске на наборе данных размеров обсуждается в ОП, этот метод вычисляет на мой MBA в чуть более 200 мс:

In [5]: window_size = 450 
In [6]: data = range(70000) 
In [7]: stride = 30 
In [8]: timeit [ np.mean(data[i:i+window_size]) for i in range(0, len(data), stride) 
       if i+window_size <= len(data) ] 
1 loops, best of 3: 220 ms per loop 

Это примерно в два раза быстрее на моей машине к itertools подхода представленный @Abhijit:

In [9]: timeit map(np.mean, izip(*(islice(it, i, None, stride) for i, it in enumerate(tee(data, window_size))))) 
1 loops, best of 3: 436 ms per loop 
+0

Какова эффективность массовых данных? – zhangxaochen

+0

@zhangxaochen: Я добавил контрольный показатель скорости для набора данных, упомянутого в OP. – mdml

+0

похоже, решение Abhijit намного быстрее: * 6.19 мс за цикл * – zhangxaochen

1

следующий подход использует itertools на полную катушку, чтобы создать скользящее среднее окно размером 4. Поскольку целым выражением является генератор, который вычисляется при вычислении среднего значения, он имеет сложность O (n).

>>> import numpy as np 
>>> from itertools import count, tee, izip, islice 
>>> map(np.mean, izip(*(islice(it,i,None,2) 
         for i, it in enumerate(tee(data, 4))))) 
[2.5, 4.5, 6.5, 8.5] 

Его интересно отметить, как индивидуальная функция itertools работает в согласии.

  1. itertools.tee н-plicates итератора, в данном случае 4 раза
  2. перечисление создает объект перечислителя, которые дают кортеж индекса и элемент (который является итератором)
  3. среза итератора с шагом 2, начиная с позиции индекса.
+0

Спасибо за вашу помощь! Это больше похоже на то, что я ожидал с реализацией itertools и очень информативно. Я удивлен, что это на самом деле медленнее, чем другой ответ, поскольку я понял, что itertools быстрее, чем использование во многих случаях понимания списка. При этом я выбираю ответ mdml, потому что он быстрее и читабельнее. – limi44