Вопрос по sum, average, plot, python – Нахождение скользящей средней по точкам данных в Python

41

Я снова немного играю в Python, и я нашел аккуратную книгу с примерами. Одним из примеров является представление некоторых данных. У меня есть файл .txt с двумя столбцами, и у меня есть данные. Я нанес на карту данные очень хорошо, но в упражнении говорится: «Измените вашу программу дальше, чтобы вычислить и построить график скользящего среднего значения данных, определяемого как:

$Y_k=\frac{1}{2r}\sum_{m=-r}^r y_{k+m}$

гдеr=5 в этом случае (иy_k это второй столбец в файле данных). Пусть программа отобразит как исходные данные, так и скользящее среднее на одном графике.

Пока у меня есть это:

from pylab import plot, ylim, xlim, show, xlabel, ylabel
from numpy import linspace, loadtxt

data = loadtxt("sunspots.txt", float)
r=5.0

x = data[:,0]
y = data[:,1]

plot(x,y)
xlim(0,1000)
xlabel("Months since Jan 1749.")
ylabel("No. of Sun spots")
show()

Так как мне рассчитать сумму? В Mathematica это просто, поскольку это символическое манипулирование (например, Sum [i, {i, 0,10}]), но как вычислить сумму в python, которая берет каждые десять точек в данных и усредняет их, и делает так до конца очков?

Я посмотрел на книгу, но не нашел ничего, что могло бы объяснить это:

код хелтонбайкера сделал свое дело ^^: D

from __future__ import division
from pylab import plot, ylim, xlim, show, xlabel, ylabel, grid
from numpy import linspace, loadtxt, ones, convolve
import numpy as numpy

data = loadtxt("sunspots.txt", float)

def movingaverage(interval, window_size):
    window= numpy.ones(int(window_size))/float(window_size)
    return numpy.convolve(interval, window, 'same')

x = data[:,0]
y = data[:,1]


plot(x,y,"k.")
y_av = movingaverage(y, 10)
plot(x, y_av,"r")
xlim(0,1000)
xlabel("Months since Jan 1749.")
ylabel("No. of Sun spots")
grid(True)
show()

И я получил это:

image

Большое спасибо ^^ :)

Я думаю, что нам нужно использовать & quot; действительный & quot; вместо "того же самого" здесь - вернуть numpy.convolve (интервал, окно, «то же») ekta
Это странно. Поскольку у нас нет вашего txt-файла, здесь невозможно протестировать, но я думаю, чтоxlim линия не должна использоваться (на всякий случай) heltonbiker
Я сделал ошибку в коде! Вы должны выполнить среднее значение для массива y, а не x:y_av = movingaverage(y, r) plot(x, y_av), И вы можете снова использовать xlim, я думаю. heltonbiker
Я получил очки отсюда:www-personal.umich.edu/~mejn/computational-physics/sunspots.dat  И удаление xlim не помогло: \ dingo_d
Потрясающие! : D Спасибо ^^ dingo_d

Ваш Ответ

7   ответов
0

Я думаю что-то вроде:

aves = [sum(data[i:i+6]) for i in range(0, len(data), 5)]

Но я всегда должен дважды проверять, что индексы делают то, что я ожидаю. Требуемый диапазон (0, 5, 10, ...) и данные [0: 6] предоставят вам данные [0] ... данные [5]

ETA: упс, и вы хотите ave, а не sum, конечно. Итак, на самом деле, используя ваш код и формулу:

r = 5
x = data[:,0]
y1 = data[:,1]
y2 = [ave(y1[i-r:i+r]) for i in range(r, len(y1), 2*r)]
y = [y1, y2]
В любом случае, у y1 есть точки len (y1), а у y2 есть точки len (y1) / 2r, так что ... вы хотите добавить их отдельно в график. Вместо этого используйте извилистые решения!
С этим я получаю кучу массивов, и я получаю ошибки, когда я пытаюсь построить их: \ dingo_d
Опять же, для y2 я получаю, что они [массив [число, число], массив [число, число] ...]: \ Мне нужно получить числа для построения: \ dingo_d
Извините, опечатка не исправлена, вместо данных должно быть y1 [i-r: i + r]
1

Моя функция скользящего среднего, без функции numpy:

from __future__ import division  # must be on first line of script

class Solution:
    def Moving_Avg(self,A):
        m = A[0]
        B = []
        B.append(m)
        for i in range(1,len(A)):
            m = (m * i + A[i])/(i+1)
            B.append(m)
        return B
@Arnanda_An, Вы можете форсировать деление в Python 2, используя десятичную точку в1: m = (m * i + A[i])/(i+1.)
Извините, что добавили первую строку: изfuture импортное подразделение. В противном случае вывод будет int вместо float
25

Скользящее среднее - это свертка, и numpy будет быстрее, чем большинство чистых операций с Python. Это даст вам 10-балльную скользящую среднюю.

import numpy as np
smoothed = np.convolve(data, np.ones(10)/10)

Я бы тожеstrongly предложите использовать пакет великолепных панд, если вы работаете с данными временных рядов. Есть несколько хорошихвстроенные в скользящие средние операции.

+10 к & quot; использовать панд & quot; предложение. Не идеально для каждого случая, но, вероятно, избавляет от головной боли, когда кто-то читает этот пост
@reptilicus, кажется, это круто, но, похоже, это не улучшит аналогичную проблему, с которой я столкнулся здесь, и я был бы признателен, если бы вы взглянули на это.stackoverflow.com/questions/45839123/…
Я получаю сообщение об ошибке: Traceback (последний вызов был последним): файл & quot; C: / Users / ***** / Desktop / sunspots_plot.py & quot ;, строка 7, в & lt; module & gt; smoothed = np.convolve (data, np.ones (10) / (10)) Файл & quot; C: \ Python26 \ lib \ site-packages \ numpy \ core \ numeric.py & quot ;, строка 787, в сложенном виде возвращает несколько массивов. correlate (a, v [:: - 1], mode) ValueError: объект слишком глубокий для нужного массива dingo_d
То есть данные b / c в вашем случае являются многомерным массивом numpy, и вы должны передавать одномерный массив. В вашем случае это будет сглажено = np.convolve (y, np.ones / 10)
47

Какnumpy.convolve довольно медленно, те, кто нуждается в быстродействующем решении, могут предпочесть более простое для пониманияcumsum подход. Вот код:

cumsum_vec = numpy.cumsum(numpy.insert(data, 0, 0)) 
ma_vec = (cumsum_vec[window_width:] - cumsum_vec[:-window_width]) / window_width

гдеdata содержит ваши данные, иma_vec будет содержать скользящие средниеwindow_width длина.

В среднем,cumsum примерно в 30-40 раз быстрее, чемconvolve.

где «шаг»; параметр?
Это дубликат этого старого вопроса:stackoverflow.com/a/27681394/1391441
@ roman-kh, я был бы признателен, если бы вы взглянули на это, и спасибо.stackoverflow.com/questions/45839123/…
Я думаю, что если бы я внедрил скользящее среднее в автономном режиме сегодня, я бы использовал ваше решение с самого начала, а не сгибал. На самом деле, я удивлен, что этот ответ не получил гораздо больше голосов ...
4
ravgs = [sum(data[i:i+5])/5. for i in range(len(data)-4)]

Это не самый эффективный подход, но он даст ваш ответ, и мне неясно, будет ли ваше окно 5 баллов или 10. Если его 10, замените каждые 5 на 10, а 4 на 9.

74

Before reading this answer, bear in mind that there is another answer below, from Roman Kh, which uses numpy.cumsum and is MUCH MUCH FASTER than this one.

Best Одним из распространенных способов применения скользящего среднего / скользящей средней (или любой другой функции скользящего окна) к сигналу является использованиеnumpy.convolve().

def movingaverage(interval, window_size):
    window = numpy.ones(int(window_size))/float(window_size)
    return numpy.convolve(interval, window, 'same')

Здесь интервал вашx массив иwindow_size количество образцов для рассмотрения. Окно будет отцентрировано по каждому сэмплу, поэтому оно берет сэмплы до и после текущего сэмпла, чтобы вычислить среднее значение. Ваш код станет:

plot(x,y)
xlim(0,1000)

x_av = movingaverage(interval, r)
plot(x_av, y)

xlabel("Months since Jan 1749.")
ylabel("No. of Sun spots")
show()

Надеюсь это поможет!

Я считаю, что это решение работает очень хорошо, но не работает на границах данных. Это добавляет ложные низкие значения.
Здесь я получаю сообщение об ошибке: Traceback (последний вызов был последним): файл & quot; C: / Users / ***** / Desktop / sunspots_plot.py & quot ;, строка 18, в & lt; module & gt; x_av = movingaverage (x, 5) Файл & quot; C: / Users / ***** / Рабочий стол / sunspots_plot.py & quot ;, строка 8, в movingaverage window = numpy.ones (int (window_size)) / float (window_size) NameError: глобальное имя «numpy» не определено dingo_d
Проблема в том, чтоconvolve очень медленно Ниже вы можете найти гораздо более быстрое решение на основеnumpy.cumsum().
Ну, это означает, что вы не импортировали NumPy. Фактически, вы импортировали из него только некоторые функции:linspace а такжеloadtxt, Вы должны добавитьones а такжеconvolve к этому; о)
Я отредактировал свой код, и теперь у меня есть изображение, но среднее значение находится только на последней части графика. Должен ли я вручную изменить интервал, чтобы разобраться с этим? dingo_d
4

Есть проблема с принятым ответом. Я думаю, что мы должны использовать"valid" вместо"same" Вот -return numpy.convolve(interval, window, 'same') .

В качестве примера попробуйте MA этого набора данных =[1,5,7,2,6,7,8,2,2,7,8,3,7,3,7,3,15,6] - результат должен быть[4.2,5.4,6.0,5.0,5.0,5.2,5.4,4.4,5.4,5.6,5.6,4.6,7.0,6.8], но имеющий "то же самое" дает нам неправильный вывод[2.6,3.0,4.2,5.4,6.0,5.0,5.0,5.2,5.4,4.4,5.4,5.6,5.6, 4.6,7.0,6.8,6.2,4.8]

Расти код, чтобы попробовать это -:

result=[]
dataset=[1,5,7,2,6,7,8,2,2,7,8,3,7,3,7,3,15,6]
window_size=5
for index in xrange(len(dataset)):
    if index <=len(dataset)-window_size :
        tmp=(dataset[index]+ dataset[index+1]+ dataset[index+2]+ dataset[index+3]+ dataset[index+4])/5.0
        result.append(tmp)
    else:
      pass

result==movingaverage(y, window_size) 

Попробуйте это с действительным & amp; то же самое и посмотреть, имеет ли математика смысл.

Смотрите также -:http://sentdex.com/sentiment-analysisbig-data-and-python-tutorials-algorithmic-trading/how-to-chart-stocks-and-forex-doing-your-own-financial-charting/calculate-simple- скользящий средний-см-Python /

Мне жаль, что я не вернулся к вам, я тогда не мог заставить Python работать над моей компью, поэтому я забыл об этом. Я установил его снова и попытался установить'valid' вconvolveи получил ошибкуValueError: x and y must have same first dimension, Я проверил длину моего массива, и они были одинаковыми. Я даже сделалx = numpy.array(data[:,0]) y = numpy.array(data[:,1]), но я все еще получил ту же ошибку. dingo_d
Я не пробовал это, но я посмотрю на это, прошло много времени с тех пор, как я закодировал на Python. dingo_d
Я сейчас на работе, поэтому у меня нет доступа к Python, но когда я дома, я попробую :) dingo_d
@dingo_d Почему бы вам быстро не попробовать это с помощью ржавого кода (и примера набора данных (в виде простого списка), который я опубликовал? Для некоторых ленивых людей (как я был вначале)) - это маскирует тот факт, эта скользящая средняя неверна. Вероятно, вам следует рассмотреть возможность редактирования своего исходного ответа. Я пробовал его только вчера, и двойная проверка спасла меня от плохого представления отчетов на уровне Cxo. Все, что вам нужно сделать, это попробовать одну и ту же скользящую среднюю один раз "действительный" и в другой раз с "таким же" - и как только вы убедитесь, дайте мне немного любви (иначе голосование)

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