Ответ 1
Вместо индексации вы можете приблизиться к этому с точки зрения обработки сигналов. Вы в основном выполняете дискретную свертку вашего входного сигнала с ядром с 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. Мы собираем эти четыре элемента и усредняем их, а затем пропускаем все в массиве до тех пор, пока не закончим.
Кстати, мне все еще нравится свертка.