Вместо индексации вы можете приблизиться к этому с точки зрения обработки сигналов. Вы в основном выполняете discrete convolution вашего входного сигнала с ядром с 7 кранами, где три коэффициента центра равны 0, а конечности равны 1, и поскольку вы хотите вычислить среднее значение, вам нужно умножить все значения на (1/4)
. Однако вы не вычисляете свертку всех элементов, но мы рассмотрим это позже. Один из способов заключается в использовании scipy.ndimage.filters.convolve1d
для этого:
import numpy as np
from scipy.ndimage import filters
d = np.arange(1, 21, dtype=np.float)
ker = (1.0/4.0)*np.array([1,1,0,0,0,1,1], dtype=np.float)
out = filters.convolve1d(d, ker)[3:-3:2]
Поскольку вы используете ядро, 7 водопроводную, свертка продлит выход на 3 слева и 3 справа, так что вам нужно, чтобы убедиться, вырезать первый и последний три элемента. Вы также хотите, чтобы пропускал каждый элемент, потому что свертка включает скользящее окно, но вы хотите отбросить все остальные элементы, чтобы получить нужный результат.
Мы получаем это для out
:
In [47]: out
Out[47]: array([ 4., 6., 8., 10., 12., 14., 16.])
Чтобы перепроверить, чтобы увидеть, если у нас есть правильный результат, попробуйте некоторые вычисления выборки для каждого элемента. Первый элемент равен (1+2+6+7)/4 = 4
. Второй элемент равен (3+4+8+9)/4 = 6
и т. Д.
Для решения с меньшим количеством головных болей, попробуйте numpy.convolve
с mode=valid
флагом. Это позволяет избежать вырезания из дополнительных накладок слева и справа, но вам все равно придется пропустить любой другой элемент, хотя:
import numpy as np
d = np.arange(1, 21, dtype=np.float)
ker = (1.0/4.0)*np.array([1,1,0,0,0,1,1], dtype=np.float)
out = np.convolve(d, ker, mode='valid')[::2]
Мы также получаем:
In [59]: out
Out[59]: array([ 4., 6., 8., 10., 12., 14., 16.])
Наконец, если вы хотите индексации, что-то вроде этого может быть достаточно:
length = len(d[6::2])
out = np.array([(a+b+c+e)/4.0 for (a,b,c,e) in zip(d[::2][:length], d[1::2][:length], d[5::2][:length], d[6::2])])
Мы получаем:
In [69]: out
Out[69]: array([ 4., 6., 8., 10., 12., 14., 16.])
Это действительно уродливое, но оно работает. Общая длина вашего сигнала определяется тем, что конец каждого окна находится в 7-м индексе. Длина этого массива, который содержит эти индексы, определяет конечную длину вашего сигнала. Также обратите внимание, что для элемента в окне его следующий элемент можно найти, пропуская все остальные элементы до конца массива. Всего 4 из этих последовательностей, и мы просто zip
по этим 4 последовательностям, где каждая последовательность пропускает каждый другой элемент, но есть смещение, с которого мы начинаем.Первая последовательность начинается со смещения 0, следующего в 1, следующего в 5 и следующего в 6. Мы собираем эти четыре элемента и усредняем их, а затем пропускаем все в массиве до тех пор, пока не закончим.
BTW, мне все еще нравится свертка лучше.
Как вы выбрали эти цифры 1,2,6,7? Каковы правила? –
@omri_saadon два последовательных элемента и после 5 элементов другие два последовательных элемента. – Borys
Я вижу, что здесь вы сделали интерполированные данные, возможно, данные изображения. Почему бы не перефразировать вопрос, чтобы было ясно, какая последовательность вам нужна для каждого из двух наборов? – gburton