简体   繁体   中英

Generate new matrix from A containing the average value of A rows for each column if B[i, j] == 1 where B is an adjacency matrix

How can we get a new matrix containing the average value of A row for each column if B[i,j] == 1?

Suppose we have a matrix A(3,4) and a matrix B(3,3)

A =  [1      2     3      4
      15     20    7      10 
      0      5     18     12]

And an adjacency matrix

 B = [1    0     1   
      0    0     1    
      1    1     1 ]  

Expected output matrix C which takes the average value of the connected pixels in B:

for example [(1+0)/2 (2+5)/2 (3+18)/2 (4+12)/2] so we get [0.5, 3.5 10.5 8] in the first row.

           C =[0.5     3.5   10.5   8
               0        5     18   12
               5.33    9      9.33   8.66]

To find the neighborhood of each i, I implemented the following code:

for i in range(A.shape[0]):
    for j in range(A.shape[0]):
        if (B[i,j] == 1):
            print(j)

You can form the sums you need by matrix multiplying:

>>> A = np.array([[1, 2, 3, 4], [15, 20, 7, 10], [0, 5, 18, 12]])
>>> B = np.array([[1, 0, 1], [0, 0, 1], [1, 1, 1]])

>>> summed_groups = B@A
>>> summed_groups
array([[ 1,  7, 21, 16],
       [ 0,  5, 18, 12],
       [16, 27, 28, 26]])

To get the means normalize by the number of terms per group:

>>> group_sizes = B.sum(axis=1,keepdims=True)
>>> group_sizes
array([[2],
       [1],
       [3]])

>>> summed_groups / group_sizes
array([[ 0.5       ,  3.5       , 10.5       ,  8.        ],
       [ 0.        ,  5.        , 18.        , 12.        ],
       [ 5.33333333,  9.        ,  9.33333333,  8.66666667]])

Side note: you could also get the group sizes by matrix multiplication:

>>> group_sizes_alt = B@np.ones((len(A),1))
>>> group_sizes_alt
array([[2.],
       [1.],
       [3.]])

It is convenient to use boolean indexing. For example,

>>> A[[True, False, True], :]

array([[ 1,  2,  3,  4],
       [ 0,  5, 18, 12]])

this selects rows 0 and 2 of the A matrix. You can loop over the columns of B and construct the C matrix:

A = np.array([[1, 2, 3, 4], [15, 20, 7, 10], [0, 5, 18, 12]])
B = np.array([[1, 0, 1], [0, 0, 1], [1, 1, 1]]).astype(bool)
C = np.array([A[B[:, i], :].mean(axis=0) for i in range(A.shape[0])])
print(np.around(C, 2))

Result:

[[ 0.5   3.5  10.5   8.  ]
 [ 0.    5.   18.   12.  ]
 [ 5.33  9.    9.33  8.67]]

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM