Olbert Daemmerer
Olbert Daemmerer

Reputation: 141

Modifying a part of the main diagonal of a 2d-numpy array

I'm having problems with the following task.

Assume we have a matrix, looking like this:

Mat = np.array([
    [11, 12, 13, 14, 15], \
    [21, 22, 23, 24, 25], \
    [31, 32, 33, 34, 35], \
    [41, 42, 43, 44, 45], \
    [51, 52, 53, 54, 55]])

What I want to do is to replace the entries 22, 33 and 44 with something different that I calculated before. I know I could do this with for loops but I think there has to be a more elegant way.

I have something like this in mind:

  1. Subselect the main diagonal from [1,1] to [-2,-2] and save it as an array.
  2. Modify this array in the desired manner.
  3. Save the modified array as part of the main diagonal of the matrix.

I found the np.diagonal() to get the diagonal and got so far:

Mat = np.array([
[11, 12, 13, 14, 15], \
[21, 22, 23, 24, 25], \
[31, 32, 33, 34, 35], \
[41, 42, 43, 44, 45], \
[51, 52, 53, 54, 55]])

print(Mat)

snipA = Mat.diagonal()
snipB = snipA[1:len(snipA)-1]
print(snipA)
print(snipB)

There are two problems now. First, I cannot modify snipB in any way. I get the error: "output array is read-only". Second, how can I save a modified snipB into the matrix again?

Any help is appreciated.

Upvotes: 2

Views: 81

Answers (2)

Daniel F
Daniel F

Reputation: 14399

You can also do this with einsum since numpy 1.10

np.einsum('ii->i', mat)[1:-1] = 0

mat 
array([[11, 12, 13, 14, 15],
       [21,  0, 23, 24, 25],
       [31, 32,  0, 34, 35],
       [41, 42, 43,  0, 45],
       [51, 52, 53, 54, 55]])

Upvotes: 0

Moses Koledoye
Moses Koledoye

Reputation: 78554

You can index and modify a part of the diagonal like so:

>>> subdiag = np.arange(1, len(mat)-1)
>>> mat[subdiag, subdiag]
array([22, 33, 44])
>>> mat[subdiag, subdiag] = 0
>>> mat
array([[11, 12, 13, 14, 15],
       [21,  0, 23, 24, 25],
       [31, 32,  0, 34, 35],
       [41, 42, 43,  0, 45],
       [51, 52, 53, 54, 55]])
>>>
>>> mat[subdiag, subdiag] = [22, 33, 44]
>>> mat
array([[11, 12, 13, 14, 15],
       [21, 22, 23, 24, 25],
       [31, 32, 33, 34, 35],
       [41, 42, 43, 44, 45],
       [51, 52, 53, 54, 55]])

Upvotes: 3

Related Questions