Функция суммирования с использованием срезов с массивом numpy Python

#python #numpy #sum #slice #numpy-ndarray

#python #numpy #сумма #срез #numpy-ndarray

Вопрос:

Есть ли способ, которым я мог бы индексировать через список numpy, точно так же, как я мог бы это сделать в обычной функции списка. Я хочу просмотреть 3 элемента в списке, каждый раз поднимаясь на одну точку и суммируя все срезы. Таким образом, он будет проходить 1,2,3 для первой суммы, а затем он будет проходить 2,3,4 для второй суммы и т.д. Приведенный ниже код выдает мне скалярную ошибку, есть ли способ, которым я мог бы выполнить приведенную ниже функцию без использования цикла for.

 import numpy as np
n = 3 
arr = np.array([1, 2, 3, 4, 5, 6, 7, 8,9, 10, 11,12, 13, 14, 15, 16, 17, 18, 19, 20, 21 ,22, 23, 24, 25])
start = np.arange(0, len(arr)-n, 1)
stop = np.arange(n-1, len(arr), 1)
sum_arr = np.sum(arr[start:stop])
 

Комментарии:

1. [n:m] требуются скалярные значения, а не массивы. Это верно только при использовании в массивах, как в списках. Почему вы не использовали понимание списка?

2. @hpaulj Я не хочу использовать понимание списка с циклом for, поскольку он медленный. Если возможно, я просто хочу использовать массивы.

3. Для начала лучше использовать что-то медленное, но работающее, а не пытаться угадать «я надеюсь, что это сработает»! Но есть ряд альтернатив для moving-windows as_strided , convolving , cumsum , и т.д.

Ответ №1:

Я думаю, это должно сработать:

 sum_arr = arr[1:-1]   arr[2:]   arr[:-2]
 

Это создает массив, который на два значения короче, чем arr, потому что у последнего элемента в arr нет двух дополнительных элементов для создания суммы.

Если вы хотите, чтобы массив имел ту же длину, что и исходный arr, вы могли бы добавить два дополнительных нуля к массиву arr следующим образом:

 arr = np.append(arr, [0, 0])
sum_arr = arr[1:-1]   arr[2:]   arr[:-2]
 

Комментарии:

1. Разве нет лучшей версии, в которой я мог бы указать количество массивов для суммирования функции с помощью like вместо того, чтобы брать 3 числа, я бы сказал, 5 и т.д.

2. Я также обновил его, поскольку также не смог определить проблему.

Ответ №2:

Для суммирования скользящего диапазона n элементов вы можете использовать convolve1d все веса, установленные на 1 . Используйте 'constant' граничный режим со значением заполнения по умолчанию 0 . Поскольку окно фильтра по умолчанию центрировано, вам необходимо настроить длину результата с обоих концов.

 import numpy as np 
from scipy.ndimage import convolve1d

arr = np.arange(1,26)

for n in range(2,6):
   k,r = divmod(n, 2)
   print(n, convolve1d(arr, np.ones(n), mode='constant')[k r-1:-k])
 

Результат:

 2 [ 3  5  7  9 11 13 15 17 19 21 23 25 27 29 31 33 35 37 39 41 43 45 47 49]
3 [ 6  9 12 15 18 21 24 27 30 33 36 39 42 45 48 51 54 57 60 63 66 69 72]
4 [ 10 14 18 22 26 30 34 38 42 46 50 54 58 62 66 70 74 78 82 86 90 94]
5 [ 15  20  25  30  35  40  45  50  55  60  65  70  75  80  85  90  95 100 105 110 115]
 

Комментарии:

1. Есть ли способ, которым я мог бы выполнить итерацию функции без цикла for. Как я объяснил в деталях выше, я пытаюсь заставить функцию работать как можно быстрее.

2. вот почему я предложил решение без цикла (цикл в примере предназначен только для демонстрации разных размеров окна, т. Е. Для любого заданного n , например n=3 , цикла не будет, а будет только один вызов convolve1d )