DilithiumMatrix
DilithiumMatrix

Reputation: 18627

Modifying multidimensional numpy subarrays indexed by lists

Lets say I have a 4x4 numpy array: quad = arange(16).reshape(4,4), i.e.

[[ 0  1  2  3]
 [ 4  5  6  7]
 [ 8  9 10 11]
 [12 13 14 15]]

and I want to change the elements with values,

[[ 5  7]
 [ 9 11]]

to (for example),

[[16 17]
 [18 19]]

My initial guess was that I could do something like,

quad[[1,3],[1,3]] = np.arange(16,20).reshape(2,2)

but that doesn't work, as quad[[1,3],[1,3]] actually yields the elements corresponding to [5,11]. I found that I could view the appropriate elements using quad[[1,3]][:,[1,3]] but I can't use that to modify those values.

Is the only solution to use a for loop?

Upvotes: 0

Views: 137

Answers (2)

Bi Rico
Bi Rico

Reputation: 25813

You can do:

quad[np.ix_([1, 3], [1, 3])]

This is shorthand for:

x = [[1, 1], [3, 3]]
y = [[1, 3], [1, 3]]
quad[x, y]

Upvotes: 4

Andrey Sobolev
Andrey Sobolev

Reputation: 12683

This is a behaviour of integer indexing in Numpy. If you give as index of an N-dimentional array A a tuple (m_1...m_n) of N 1d arrays of size M, then the slice is constructed as

result[m_1, ..., m_n] == np.array([A[m_1[0], ..., m_n[0]], A[m_1[1], ..., m_n[1]],
                           ..., A[m_1[M], ..., m_n[M]]]

To overcome this behaviour, you can use slice indexing twice:

>>> a = np.arange(16).reshape(4,4)
>>> a[1:3][:,1:3]
array([[ 5,  6],
       [ 9, 10]])

UPD: You can modify this view:

>>> b = np.arange(16,20).reshape(2,2)
>>> b
array([[16, 17],
       [18, 19]])
>>> a[1:3][:,1:3] = b
>>> a
array([[ 0,  1,  2,  3],
       [ 4, 16, 17,  7],
       [ 8, 18, 19, 11],
       [12, 13, 14, 15]])

Upvotes: 1

Related Questions