2013-08-16 4 views
6

Я хочу найти быстрый способ (без цикла) в Python, чтобы назначить reoccuring индексы массива. Это желаемый результат, используя для цикла:Назначение одинаковых индексов массива сразу в Python/Numpy

import numpy as np 
a=np.arange(9, dtype=np.float64).reshape((3,3)) 
# The array indices: [2,3,4] are identical. 
Px = np.uint64(np.array([0,1,1,1,2])) 
Py = np.uint64(np.array([0,0,0,0,0])) 
# The array to be added at the array indices (may also contain random numbers). 
x = np.array([.1,.1,.1,.1,.1]) 

for m in np.arange(len(x)): 
    a[Px[m]][Py[m]] += x 

print a 
%[[ 0.1 1. 2.] 
%[ 3.3 4. 5.] 
%[ 6.1 7. 8.]] 

Когда я пытаюсь добавить x к a в индексах Px,Py я, очевидно, не получить тот же результат (3.3 против 3.1):

a[Px,Py] += x 
print a 
%[[ 0.1 1. 2.] 
%[ 3.1 4. 5.] 
%[ 6.1 7. 8.]] 

Есть ли способ сделать это с помощью numpy? Благодарю.

+0

Прежде всего, я бы группировать значения вместе, так что у вас есть список кортежей (Px, Py). Затем сортируйте этот список, подсчитайте вхождения, умножьте x на это число и добавьте в массив. Но как-то numpy, похоже, пропускает двойные записи ... странно. – Dschoni

ответ

7

Да, это может быть сделано, но это немного сложнее:

# convert yourmulti-dim indices to flat indices 
flat_idx = np.ravel_multi_index((Px, Py), dims=a.shape) 
# extract the unique indices and their position 
unique_idx, idx_idx = np.unique(flat_idx, return_inverse=True) 
# Aggregate the repeated indices 
deltas = np.bincount(idx_idx, weights=x) 
# Sum them to your array 
a.flat[unique_idx] += deltas 
+0

Бах, избил меня тем же самым ответом на 4 секунды. Хотя, я искренне надеялся, что есть лучший способ сделать это. – Daniel

+0

Спасибо! Мне нравится, как вы использовали функцию np.ravel_multi_index, чтобы получить плоские индексы, а затем используйте np.bincount с параметром дополнительных весов. – Paul