Чтобы ответить на ваш основной вопрос, нужно взять срез оси X, соответствующий данным скользящего среднего.Поскольку у вас есть свертка из 100 элементов данных с окном размером 5, результат действителен для последних 96 элементов.Вы могли бы нарисовать это так:
plt.plot(vX[window - 1:], movingaverage(vY, window))
При этом ваш код может выдержать некоторую оптимизацию.Например, пустые массивы хранятся в статических буферах фиксированного размера.Каждый раз, когда вы добавляете или удаляете их, все это перераспределяется, в отличие от списков Python, в которые встроена амортизация. Всегда лучше предварительно выделить, если вы заранее знаете размер массива (что вы и делаете).
Во-вторых, запуск явного цикла редко необходим.Как правило, лучше использовать циклы «под капотом», реализованные на самом низком уровне в простых функциях.Это называется векторизацией.Генерация случайных чисел, кумулятивные суммы и инкрементные массивы полностью векторизованы в виде числа.В более общем смысле, обычно не очень эффективно смешивать вычислительные функции Python и numpy, включая random
.
Наконец, вы можете рассмотреть другой метод свертки.Я хотел бы предложить что-то на основе numpy.lib.stride_tricks.as_strided
.Это несколько загадочный, но очень эффективный способ реализовать скользящее окно с массивными массивами.Я покажу его здесь как альтернативу методу свертки, который вы использовали, но не стесняйтесь игнорировать эту часть.
В целом:
import matplotlib
import matplotlib.pyplot as plt
import numpy as np
def movingaverage(values, window):
# this step creates a view into the same buffer
values = np.lib.stride_tricks.as_strided(values, shape=(window, values.size - window + 1), strides=values.strides * 2)
smas = values.sum(axis=0)
smas /= window # in-place to avoid temp array
return smas
sampleSize = 100
min = -10
max = 10
window = 5
v_x = np.arange(sampleSize)
v_y = np.cumsum(np.random.random_integers(min, max, sampleSize))
plt.plot(v_x, v_y)
plt.plot(v_x[window - 1:], movingaverage(v_y, window))
plt.show()
Примечание к именам: в Python,имена переменных и функций условно name_with_underscore.CamelCase зарезервирован для имен классов.np.random.random_integers
использует ограничивающие границы, как и random.randint
, но позволяет вам указать количество сэмплов для генерации.Забавно, но np.random.randint
имеет исключительную верхнюю границу, больше похоже на random.randrange
.