2012-02-14 2 views
1

Предположит, три массива в NumPy:Карта массивов с повторяющимися индексами?

a = np.zeros(5) 
b = np.array([3,3,3,0,0]) 
c = np.array([1,5,10,50,100]) 

б теперь может быть использован в качестве индекса для а и с. Например:

In [142]: c[b] 
    Out[142]: array([50, 50, 50, 1, 1]) 

Есть ли способ добавить значения, связанные с повторяющимися индексами с помощью такого вида нарезки? С

a[b] = c 

Только последние значения сохраняются:

array([ 100., 0., 0., 10., 0.]) 

Я хотел бы что-то вроде этого:

a[b] += c 

, который дал бы

array([ 150., 0., 0., 16., 0.]) 

Я картирование очень большие векторы на двумерные матрицы и действительно хотел бы избежать петель ...

ответ

0

Вы могли бы сделать что-то вроде:

def sum_unique(label, weight): 
    order = np.lexsort(label.T) 
    label = label[order] 
    weight = weight[order] 
    unique = np.ones(len(label), 'bool') 
    unique[:-1] = (label[1:] != label[:-1]).any(-1) 
    totals = weight.cumsum() 
    totals = totals[unique] 
    totals[1:] = totals[1:] - totals[:-1] 
    return label[unique], totals 

И использовать его как это:

In [110]: coord = np.random.randint(0, 3, (10, 2)) 

In [111]: coord 
Out[111]: 
array([[0, 2], 
     [0, 2], 
     [2, 1], 
     [1, 2], 
     [1, 0], 
     [0, 2], 
     [0, 0], 
     [2, 1], 
     [1, 2], 
     [1, 2]]) 

In [112]: weights = np.ones(10) 

In [113]: uniq_coord, sums = sum_unique(coord, weights) 

In [114]: uniq_coord 
Out[114]: 
array([[0, 0], 
     [1, 0], 
     [2, 1], 
     [0, 2], 
     [1, 2]]) 

In [115]: sums 
Out[115]: array([ 1., 1., 2., 3., 3.]) 

In [116]: a = np.zeros((3,3)) 

In [117]: x, y = uniq_coord.T 

In [118]: a[x, y] = sums 

In [119]: a 
Out[119]: 
array([[ 1., 0., 3.], 
     [ 1., 0., 3.], 
     [ 0., 2., 0.]]) 

Я просто подумал, что это, возможно, было бы проще:

In [120]: flat_coord = np.ravel_multi_index(coord.T, (3,3)) 

In [121]: sums = np.bincount(flat_coord, weights) 

In [122]: a = np.zeros((3,3)) 

In [123]: a.flat[:len(sums)] = sums 

In [124]: a 
Out[124]: 
array([[ 1., 0., 3.], 
     [ 1., 0., 3.], 
     [ 0., 2., 0.]]) 
+0

Спасибо, это отлично работает! – brorfred

2

Оператор для массивов NumPy просто не работает так, как вы надеетесь, и я не знаю, как далеко от него работать. В работе вокруг я предлагаю использовать numpy.bincount():

>>> numpy.bincount(b, c) 
array([ 150., 0., 0., 16.]) 

Просто добавьте нули по мере необходимости.

+0

Благодарность за ответ! Теперь у меня появилась идея о существовании бинауты - она ​​будет очень полезна для других реализаций. Можно ли использовать этот подход для 2D-массивов? Моя проблема в реальном мире состоит из трех векторов элементов 10^7 (x-pos, y-pos, value), которые я сопоставляю с 2D-массивом. – brorfred

+0

@brorfred: вы можете переинтерпретировать ваш массив как 1D-массив без копирования с помощью метода 'reshape()', а затем применить 'bincount()'. –

Смежные вопросы