Как явно указать последний индекс для np.ufunc.reduceat

Скажем, у меня есть массив

data = np.arange(6)

Я хочу найти сумму всего массива и второй половины, используя np.add.reduceat.1

Если я сделаю это так:

np.add.reduceat(data, [0, 6, 3])[::2]

Я сразу получаю ошибку

IndexError: index 6 out-of-bounds in add.reduceat [0, 6)

Если я сделаю это так

np.add.reduceat(data, [0, 5, 3])[::2]

Я получаю неправильный ответ (10 должно быть 15):

array([10, 12])

Единственное решение, которое мне удалось придумать, - это замаскировать места, где необходим последний индекс, вычесть из них 1, а затем добавить туда последний элемент:

index = np.array([0, 6, 3])
mask = (index == data.size)
index[mask] -= 1
result = np.add.reduceat(data, index)
# Mask is shifted back by one because it's the previous element that needs to be updated
result[:-1][mask[1:]] += data[-1]

Тогда result[::2] дает желаемый ответ. Это похоже на гигантский кладж для чего-то, что, как я ожидал, будет элегантным однострочником (и быстрее, чем это).


1 Я от корки до корки знаю, что есть более эффективные способы сделать это. Это просто надуманный пример для иллюстрации. Настоящая проблема для этого вопроса возникла при попытке решить numpy: быстрое среднее значение с регулярными интервалами для большого количества отрезков / точек.

Как насчет np.add.reduceat(np.add.reduceat(data, [0, len(data)-1, len(data)//2]),[0,2])?

Divakar 13.09.2018 20:18

@Divakar. Неважно, я неверно истолковал скобки.

Mad Physicist 13.09.2018 20:56
0
2
146
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Я нечасто использовал reduceat, но похоже, что у вас может быть только один открытый диапазон, один add to the end.

Один из способов обойти это - заполнить массив (да, обычно я не рекомендую использовать np.append :)):

In [165]: np.add.reduceat(np.append(x,0),[0,6,3])
Out[165]: array([15,  0, 12])

или с полным объединением диапазонов:

In [166]: np.add.reduceat(np.append(x,0),[0,6,3,6])
Out[166]: array([15,  0, 12,  0])

Я опустил обычный [:: 2], чтобы прояснить, что происходит.

Я знаю, что принято ждать, прежде чем соглашаться, но это в значительной степени именно то, что я искал. Тем более, что в этом случае четко определяется отрицательный прирост.

Mad Physicist 13.09.2018 20:57

Если вам интересно, для чего я это использовал: stackoverflow.com/a/52320926/2988730

Mad Physicist 13.09.2018 21:59

Другие вопросы по теме