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