Replace sub part of matrix by another small matrix in numpy

I am new to Numpy and want to replace part of a matrix. For example, I have two matrices, A, B generated by numpy

In [333]: A = ones((5,5))

In [334]: A
Out[334]: 
array([[ 1.,  1.,  1.,  1.,  1.],
       [ 1.,  1.,  1.,  1.,  1.],
       [ 1.,  1.,  1.,  1.,  1.],
       [ 1.,  1.,  1.,  1.,  1.],
       [ 1.,  1.,  1.,  1.,  1.]])

In [335]: B
Out[335]: 
array([[ 0.1,  0.2],
       [ 0.3,  0.4]])

Eventually, I want to make A be the following matrix.

In [336]: A
Out[336]: 
array([[ 1.,  1.,  1.,  1.,  1.],
       [ 1.,  1.,  1.,  1.,  1.],
       [ 1.,  1.,  1.,  1.,  1.],
       [ 1.,  1.,  1.,  0.1,  0.2],
       [ 1.,  1.,  1.,  0.3,  0.4]])

and/or the following

In [336]: A
Out[336]: 
array([[ 1.,  1.,  1.,  0.1,  0.2],
       [ 1.,  1.,  1.,  0.3,  0.4],
       [ 1.,  1.,  1.,  1.,  1.],
       [ 1.,  1.,  1.,  1.,  1.],
       [ 1.,  1.,  1.,  1.,  1.]])

I tried like following but it didn't work. I don't have any idea now :(

A[[0,1],:][:,[3,4]] = B

or even I tried like

A[[0,1],:][:,[3,4]] = 1

to check whether the four cell are changed or not. Do you have any idea?


Solution 1:

Here is how you can do it:

>>> A[3:5, 3:5] = B
>>> A
array([[ 1. ,  1. ,  1. ,  1. ,  1. ],
       [ 1. ,  1. ,  1. ,  1. ,  1. ],
       [ 1. ,  1. ,  1. ,  1. ,  1. ],
       [ 1. ,  1. ,  1. ,  0.1,  0.2],
       [ 1. ,  1. ,  1. ,  0.3,  0.4]])

Solution 2:

In general, for example, for non-contiguous rows/cols use numpy.putmask(a, mask, values) (Sets a.flat[n] = values[n] for each n where mask.flat[n]==True)

For example

In [1]: a = np.zeros((3, 3))
Out [1]: a
array([[0., 0., 0.],
       [0., 0., 0.],
       [0., 0., 0.]])

In [2]: values = np.ones((2, 2))
Out [2]: values
array([[1., 1.],
       [1., 1.]])

In [3]: mask = np.zeros((3, 3), dtype=bool)
In [4]: mask[0,0] = mask[0,1] = mask[1,1] = mask[2,2] = True

Out [4]: mask
array([[ True,  True, False],
       [False,  True, False],
       [False, False,  True]])

In [5] np.putmask(a, mask, values)
Out [5] a
array([[1., 1., 0.],
       [0., 1., 0.],
       [0., 0., 1.]])

Solution 3:

For the first one:

In [13]: A[-B.shape[0]:, -B.shape[1]:] = B                              

In [14]: A
Out[14]: 
array([[ 1. ,  1. ,  1. ,  1. ,  1. ],                                  
       [ 1. ,  1. ,  1. ,  1. ,  1. ],                                  
       [ 1. ,  1. ,  1. ,  1. ,  1. ],                                  
       [ 1. ,  1. ,  1. ,  0.1,  0.2],                                  
       [ 1. ,  1. ,  1. ,  0.3,  0.4]])   

For second:

In [15]: A = np.ones((5,5))                                             

In [16]: A[:B.shape[0], -B.shape[1]:] = B                               

In [17]: A
Out[17]: 
array([[ 1. ,  1. ,  1. ,  0.1,  0.2],                                  
       [ 1. ,  1. ,  1. ,  0.3,  0.4],                                  
       [ 1. ,  1. ,  1. ,  1. ,  1. ],                                  
       [ 1. ,  1. ,  1. ,  1. ,  1. ],                                  
       [ 1. ,  1. ,  1. ,  1. ,  1. ]])   

Solution 4:

The following function replaces an arbitrary non-contiguous part of the matrix with another matrix.

def replace_submatrix(mat, ind1, ind2, mat_replace):
  for i, index in enumerate(ind1):
    mat[index, ind2] = mat_replace[i, :]
  return mat

Now an example of the application. We replace indices [1, 3] x [0, 3] (i.e. ind1 x ind2) of the empty 4 x 4 array x with the 2 x 2 array y of 4 different values:

x = np.full((4, 4), 0)
x
array([[0, 0, 0, 0],
       [0, 0, 0, 0],
       [0, 0, 0, 0],
       [0, 0, 0, 0]])

y = np.array([[1, 2], [5, 9]])
y
array([[1, 2],
       [5, 9]])

ind1 = [1, 3]
ind2 = [0, 3]
res = replace_submatrix(x, ind1, ind2, y)  
res  
array([[0, 0, 0, 0],
       [1, 0, 0, 2],
       [0, 0, 0, 0],
       [5, 0, 0, 9]])