Матричные строки суммирования по индексам - PullRequest
0 голосов
/ 03 мая 2018

У меня есть 3 матрицы (массивы np):
А имеет форму (n, m); B имеет форму (м, к); и С имеет форму (n, k)

Матрица C имеет только значения из набора {-1,0,1}, и это своего рода «индикатор»: если C [i, j] == 1, то я хочу добавить i-ую строку A к j-му столбцу b; и если C [i, j] == (- 1), то вычтите (0 ничего не делает).

Это легко сделать с помощью циклов, но мне интересно, есть ли векторизованный способ сделать это, который может быть быстрее?

пример кода:

C = np.array([[-1,  0,  0,  0,  1],
              [ 0,  0,  0,  0, -1],
              [ 0,  0,  0,  0, -1],
              [-1,  0,  0,  1,  1]])
a,b = np.where(C==1)
#here a=[0,3,3] and b=[4,3,4]
A[a,:] = [[0, 1, 2, 3, 4, 5, 6],
          [3, 3, 3, 3, 3, 3, 3],
          [3, 3, 3, 3, 3, 3, 3]]
B[:,b] += A[a]  #B is all 0.0 before  

ожидаемый результат:

array([[ 0.,  0.,  0.,  3.,  3.],
       [ 0.,  0.,  0.,  3.,  4.],
       [ 0.,  0.,  0.,  3.,  5.],
       [ 0.,  0.,  0.,  3.,  6.],
       [ 0.,  0.,  0.,  3.,  7.],
       [ 0.,  0.,  0.,  3.,  8.],
       [ 0.,  0.,  0.,  3.,  9.]])

фактический результат:

array([[ 0.,  0.,  0.,  3.,  3.],
       [ 0.,  0.,  0.,  3.,  3.],
       [ 0.,  0.,  0.,  3.,  3.],
       [ 0.,  0.,  0.,  3.,  3.],
       [ 0.,  0.,  0.,  3.,  3.],
       [ 0.,  0.,  0.,  3.,  3.],
       [ 0.,  0.,  0.,  3.,  3.]])

Ответы [ 2 ]

0 голосов
/ 03 мая 2018

У меня были небольшие проблемы с тем, чтобы держать все это прямо в моей голове, но я верю, что это то, что вы пытаетесь сделать:

import numpy as np

n, m, k = 2, 3, 4 

# A is full of 1s
A = np.ones((n,m))
# B is full of 0s
B = np.zeros((m,k))
# C is...  that
C = np.array([
    [ 0,  0, -1,  1],
    [ 0, -1,  1,  0]
])

# Where to add A to B
add_x, add_y = np.where(C==1)
# Where to subtract A to B
sub_x, sub_y = np.where(C==-1)

# Select columns of B and += rows of A 
# (using .T to transpose A so it's the same shape)
B[:,add_y] += A[add_x,:].T
# ditto thing above, but for -=
B[:,sub_y] -= A[sub_x,:].T
print(B)

Выход:

[[ 0. -1.  0.  1.]
 [ 0. -1.  0.  1.]
 [ 0. -1.  0.  1.]]
0 голосов
/ 03 мая 2018

Мы можем просто использовать np.add.at на транспонированном виде B -

np.add.at(B.T, b, A[a])

Пробный прогон -

In [39]: C = np.array([[-1,  0,  0,  0,  1],
    ...:               [ 0,  0,  0,  0, -1],
    ...:               [ 0,  0,  0,  0, -1],
    ...:               [-1,  0,  0,  1,  1]])
    ...: a,b = np.where(C==1)
    ...: A = np.zeros((4,7),dtype=int)
    ...: A[a,:] = np.array([[0, 1, 2, 3, 4, 5, 6],
    ...:           [3, 3, 3, 3, 3, 3, 3],
    ...:           [3, 3, 3, 3, 3, 3, 3]])

In [40]: # Initialize B
    ...: B = np.zeros((7,5),dtype=int)

In [41]: np.add.at(B.T, b, A[a])

In [42]: B
Out[42]: 
array([[0, 0, 0, 3, 3],
       [0, 0, 0, 3, 4],
       [0, 0, 0, 3, 5],
       [0, 0, 0, 3, 6],
       [0, 0, 0, 3, 7],
       [0, 0, 0, 3, 8],
       [0, 0, 0, 3, 9]])

Как commented by @DSM, мы также можем использовать матричное дублирование и, следовательно, избежать шага для получения индексов для C==1 -

A.T.dot(C==1)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...