#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
)