Один простой способ сгладить данные - использовать алгоритм скользящее среднее . Одной простой формой скользящего среднего является вычисление среднего значения соседних измерений в определенной позиции. Например, в одномерной серии измерений a [1: N] скользящее среднее при a [n] можно рассчитать как a [n] = (a [n-1] + a [n] + a [ n + 1]) / 3, например. Если вы пройдете все свои измерения, все готово. В этом простом примере наше окно усреднения имеет размер 3. Вы также можете использовать окна разных размеров, в зависимости от желаемой степени сглаживания.
Чтобы сделать вычисления более простыми и быстрыми для более широкого диапазона приложений, вы также можете использовать алгоритм, основанный на сверточности . Преимущество использования свертки состоит в том, что вы можете выбирать различные виды средних значений, например, взвешенные средние значения, просто меняя окно.
Давайте сделаем немного кодирования для иллюстрации. Следующая выдержка требует установки Numpy, Matplotlib и Scipy. Нажмите здесь для ознакомления с полным кодом образца
from __future__ import division
import numpy
import pylab
from scipy.signal import convolve2d
def moving_average_2d(data, window):
"""Moving average on two-dimensional data.
"""
# Makes sure that the window function is normalized.
window /= window.sum()
# Makes sure data array is a numpy array or masked array.
if type(data).__name__ not in ['ndarray', 'MaskedArray']:
data = numpy.asarray(data)
# The output array has the same dimensions as the input data
# (mode='same') and symmetrical boundary conditions are assumed
# (boundary='symm').
return convolve2d(data, window, mode='same', boundary='symm')
Следующий код генерирует некоторые произвольные и зашумленные данные, а затем вычисляет скользящую среднюю, используя четыре окна с разными размерами.
M, N = 20, 2000 # The shape of the data array
m, n = 3, 10 # The shape of the window array
y, x = numpy.mgrid[1:M+1, 0:N]
# The signal and lots of noise
signal = -10 * numpy.cos(x / 500 + y / 10) / y
noise = numpy.random.normal(size=(M, N))
z = signal + noise
# Calculating a couple of smoothed data.
win = numpy.ones((m, n))
z1 = moving_average_2d(z, win)
win = numpy.ones((2*m, 2*n))
z2 = moving_average_2d(z, win)
win = numpy.ones((2*m, 4*n))
z3 = moving_average_2d(z, win)
win = numpy.ones((2*m, 10*n))
z4 = moving_average_2d(z, win)
А затем, чтобы увидеть другие результаты, вот код для некоторого построения.
# Initializing the plot
pylab.close('all')
pylab.ion()
fig = pylab.figure()
bbox = dict(edgecolor='w', facecolor='w', alpha=0.9)
crange = numpy.arange(-15, 16, 1.) # color scale data range
# The plots
ax = pylab.subplot(2, 2, 1)
pylab.contourf(x, y, z, crange)
pylab.contour(x, y, z1, crange, colors='k')
ax.text(0.05, 0.95, 'n=10, m=3', ha='left', va='top', transform=ax.transAxes,
bbox=bbox)
bx = pylab.subplot(2, 2, 2, sharex=ax, sharey=ax)
pylab.contourf(x, y, z, crange)
pylab.contour(x, y, z2, crange, colors='k')
bx.text(0.05, 0.95, 'n=20, m=6', ha='left', va='top', transform=bx.transAxes,
bbox=bbox)
bx = pylab.subplot(2, 2, 3, sharex=ax, sharey=ax)
pylab.contourf(x, y, z, crange)
pylab.contour(x, y, z3, crange, colors='k')
bx.text(0.05, 0.95, 'n=40, m=6', ha='left', va='top', transform=bx.transAxes,
bbox=bbox)
bx = pylab.subplot(2, 2, 4, sharex=ax, sharey=ax)
pylab.contourf(x, y, z, crange)
pylab.contour(x, y, z4, crange, colors='k')
bx.text(0.05, 0.95, 'n=100, m=6', ha='left', va='top', transform=bx.transAxes,
bbox=bbox)
ax.set_xlim([x.min(), x.max()])
ax.set_ylim([y.min(), y.max()])
fig.savefig('movingavg_sample.png')
# That's all folks!
А вот результаты для разных размеров окон:
В приведенном здесь примере кода используется простое окно (или прямоугольное окно) в двух измерениях. Доступно несколько различных типов окон, и вы можете проверить Wikipedia для большего количества примеров.