3

I have a 3-dimensional numpy array, and I'm trying to index it along its second and third dimensions using two single-dimension numpy arrays. To wit:

np.random.seed(0)
dims = (1,5,5)
test_array = np.arange(np.prod(dims)).reshape(*dims)
test_array

produces:

array([[[ 0,  1,  2,  3,  4],
        [ 5,  6,  7,  8,  9],
        [10, 11, 12, 13, 14],
        [15, 16, 17, 18, 19],
        [20, 21, 22, 23, 24]]])

if I then create the two arrays to index it:

idx_dim1 = np.array([0,2,4])
idx_dim2 = np.array([1,3])

I find that I can't apply these both at the same time:

test_array[:,idx_dim1,idx_dim2]
---------------------------------------------------------------------------
IndexError                                Traceback (most recent call last)
<ipython-input-193-95b23ed3210c> in <module>()
----> 1 test_array[:,idx_dim1,idx_dim2]

IndexError: shape mismatch: indexing arrays could not be broadcast together with shapes (3,) (2,) 

I can split them out, by, say

test_array[:, idx_dim1,:][:,:,idx_dim2]

which gives

array([[[ 1,  3],
        [11, 13],
        [21, 23]]])

But this only works in a read-only sense - I can't assign values to test_array like this, since I'm assigning to a slice rather than the original. I'm also not quite sure why using the two indexers together doesn't work. Is there some conceptual nuance of numpy that I'm not understanding here? And is there a good solution that allows me to assign values?

Thanks!

3
  • 1
    I replaced your example with something more reproducible. Commented Nov 30, 2018 at 4:57
  • @coldspeed much obliged. Commented Nov 30, 2018 at 5:00
  • Are you coming from a MATLAB background? There selecting a block is easy, selecting a scatted set of items awkward. In numpy the block indexing is a bit more awkward, at least on the surface. But notice that the error talks about broadcasting. How would you add a shape (3,) array to a shape (2,)? The same broadcasting rules apply. Commented Nov 30, 2018 at 5:38

2 Answers 2

5

Try

test_array[:, idx_dim1[:,None], idx_dim2] = some_value

Where,

>>> test_array[:, idx_dim1[:,None], idx_dim2]
array([[[ 1,  3],
        [11, 13],
        [21, 23]]])
Sign up to request clarification or add additional context in comments.

2 Comments

Thanks, that's right on the money. But why is that necessary?
@Chrisper It's a little complicated. Thankfully, the docs should be able to explain it much better than I can. I would recommend starting here.
1

To index cross products (rectangular subsets) of arrays, use np.ix_

A = np.zeros(( 1, 5, 5 ))
A[np.ix_( [0], [0,2,4], [1,3] )] = 1
# print dot0( A )
[[[. 1 . 1 .]
  [. . . . .]
  [. 1 . 1 .]
  [. . . . .]
  [. 1 . 1 .]]]

You can also set cross products with ix_ —

B = np.arange( 3 * 2 ).reshape( 3, 2 )
A[np.ix_( [0], [0,2,4], [1,3] )] = B

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.