numpy — есть ли способ вызвать многократные приращения в arr[1, [0, 2, 0, 2, 0]] = 1

#numpy

#тупой

Вопрос:

Предыстория

1 встречается только один раз для каждого элемента, хотя на каждый индексированный элемент ссылаются несколько раз.

 a = np.arange(12).reshape((3, 4))
b = a.copy()
print(a)
---
[[ 0  1  2  3]
 [ 4  5  6  7]
 [ 8  9 10 11]]

a[1, [0, 2, 0, 2, 0]]  = 1  #  a[1][0] referenced 3 times and a[1][2] 2 times
print(a-b)
---
[[0 0 0 0]
 [1 0 1 0]   # <---  1 occurs only once for a[1][0] and a[1][2]
 [0 0 0 0]]
 

Вопрос

Есть ли способ создать своего рода накопительное дополнение, подобное приведенному ниже, простым способом?

 # Result a
[[ 0  1  2  3]
 [ 7  5  8  7]    <---  1 three times on a[1][0] and twice on a[1][2]
 [ 8  9 10 11]]

# a-b
[[0 0 0 0]
 [3 0 2 0]   # <---  3 for a[1][0] and  2 for a[1][2]
 [0 0 0 0]]
 

Одним из способов может быть сокращение, похожее на отображение / уменьшение количества слов, но хотелось бы знать, существует ли собственный способ numpy.

введите описание изображения здесь

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

1. Я думаю, ты хочешь np.add.at(a[1], [0, 2, 0, 2, 0], 1)

Ответ №1:

То, что вы ищете, это numpy.ufunc.at . Вот как вы можете использовать это в вашем случае:

 np.add.at(a, (1, [0, 2, 0, 2, 0]), 1)

print(a - b)
# [[0 0 0 0]
#  [3 0 2 0]
#  [0 0 0 0]]
 

Из документов:

Выполняет небуферизованную операцию на месте над операндом ‘a’ для элементов, указанных ‘indexes’. Для добавления ufunc этот метод эквивалентен a[indices] = b , за исключением того, что результаты накапливаются для элементов, которые индексируются более одного раза. Например, a[[0,0]] = 1 будет увеличивать первый элемент только один раз из-за буферизации, тогда add.at(a, [0,0], 1) как будет увеличивать первый элемент дважды.

Ответ №2:

Пока это накопительное дополнение может работать по одной оси за раз — вы можете использовать collections.Counter .

Рассмотрим следующее:

 import numpy as np
from collections import Counter

a = np.arange(12).reshape((3, 4))
b = a.copy()

add_lst = [0, 2, 0, 2, 0]
add_lst = Counter(add_lst)
a[1, list(add_lst.keys())]  = list(add_lst.values())
print(a-b)
 

Результаты:

 [[0 0 0 0]
 [3 0 2 0]
 [0 0 0 0]]