Картографические массивы с дублирующимися индексами? - PullRequest
1 голос
/ 14 февраля 2012

Предположим, что три массива в numpy:

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

b теперь можно использовать как индекс для a и c.Например:

   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.])

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

Ответы [ 2 ]

2 голосов
/ 14 февраля 2012

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

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

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

0 голосов
/ 15 февраля 2012

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

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.]])
...