wzboss
wzboss

Reputation: 17

numpy equivalent command for Matlab 2D indexing A([],[])

I am looking for exact command in Numpy for following Matlab indexing.

Uploaded as picture: [1]: https://i.sstatic.net/Q2DJ0.png

I have tried to do similar thing in Numpy:

kk = np.zeros((100,100))
k= np.array([[ 0,  1,  2],
              [ 3,  4,  5],
              [ 6,  7,  8]])
kk[[9,2,7],[9,2,7]] = k

But this will throw you error:

ValueError: shape mismatch: value array of shape (3,3) could not be broadcast to indexing result of shape (3,)

i edit this question, in my case, each indexing is not contiguous, but they are the same for example: kk[[9,2,7],[9,2,7]].

Upvotes: 0

Views: 132

Answers (1)

norok2
norok2

Reputation: 26886

If the indexing is contiguous you should use slice()s:

import numpy as np


kk = np.zeros((6, 7), dtype=int)
k = np.arange(2 * 3).reshape((2, 3)) + 1
kk[1:3, 1:4] = k
   
print(kk)
# [[0 0 0 0 0 0 0]
#  [0 1 2 3 0 0 0]
#  [0 4 5 6 0 0 0]
#  [0 0 0 0 0 0 0]
#  [0 0 0 0 0 0 0]
#  [0 0 0 0 0 0 0]]

Note that a:b:c inside [] is sugar syntax for slice(a, b, c), with :c/, c optional and if a/b should be None this can be left out in the shortcut (but not in the functional version) and if only one parameter is set to slice(), this is assigned to b.

Otherwise, you could use numpy.ix_():

import numpy as np


kk = np.zeros((6, 7), dtype=int)
k = np.arange(2 * 3).reshape((2, 3)) + 1
kk[np.ix_((1, 3), (1, 2, 4))] = k
   
print(kk)
# [[0 0 0 0 0 0 0]
#  [0 1 2 0 3 0 0]
#  [0 0 0 0 0 0 0]
#  [0 4 5 0 6 0 0]
#  [0 0 0 0 0 0 0]
#  [0 0 0 0 0 0 0]]

Slices are typically way faster and more memory efficient than advanced indexing, and you should prefer them when possible.

Note that np.ix_() is just producing index arrays with the correct shapes to trigger the desired indexing:

np.ix_((1, 3), (1, 2, 4))
# (array([[1],
#         [3]]), array([[1, 2, 4]]))

Hence, the following would work:

import numpy as np


kk = np.zeros((6, 7), dtype=int)
k = np.arange(2 * 3).reshape((2, 3)) + 1
kk[np.array([1, 3])[:, None], np.array([1, 2, 4])[None, :]] = k
   
print(kk)
# [[0 0 0 0 0 0 0]
#  [0 1 2 0 3 0 0]
#  [0 0 0 0 0 0 0]
#  [0 4 5 0 6 0 0]
#  [0 0 0 0 0 0 0]
#  [0 0 0 0 0 0 0]]

Also, slices and np.ndarray(dtype=int) can be combined together:

import numpy as np


kk = np.zeros((6, 7), dtype=int)
k = np.arange(2 * 3).reshape((2, 3)) + 1
kk[1:4:2, np.array([1, 2, 4])] = k
   
print(kk)
# [[0 0 0 0 0 0 0]
#  [0 1 2 0 3 0 0]
#  [0 0 0 0 0 0 0]
#  [0 4 5 0 6 0 0]
#  [0 0 0 0 0 0 0]
#  [0 0 0 0 0 0 0]]

Upvotes: 1

Related Questions