2

According the the numpy documentation, specifying array indices as array_name[x, y] and array_name[x][y] are equivalent, and should produce the same result. However, the following code snippet:

import numpy as np

a = np.empty((7, 8, 9), dtype = object)
# First indexing notation
print(a[:, 0, 0].shape, a[0, :, 0].shape, a[0, 0, :].shape)
# Second indexing notation
print(a[:][0][0].shape, a[0][:][0].shape, a[0][0][:].shape)

produce the outputs:

(7,) (8,) (9,)    
(9,) (9,) (9,)

respectively, which are evidently not equivalent. What gives?

Karthik
  • 29
  • 4
  • 2
    Indexing with `[:]` does nothing. Even with a list it just copies. With `x[....][...][...]` you have to look at the action of each indexing operation individually. The interpreter applies them one at a time. In the `[,.., ..., ...]` `numpy` can use them together. – hpaulj Dec 12 '18 at 17:48
  • 3
    The equivalency applies only to single element indexing, not to slicing (with `:`) or advanced indexing. – hpaulj Dec 12 '18 at 17:51
  • Got it, thanks. Could you also explain what causes the Python to produce the result on the second line? – Karthik Dec 12 '18 at 18:28
  • If you omit the `[:]`, it comes down to `a[0][0]` which is the same as `a[0,0]` or `a[0,0,:]`. – hpaulj Dec 12 '18 at 18:32
  • But isn't it weird that all three of the expressions on the 2nd line evaluate to a[0, 0, :]? Is this a feature of some sort that I'm missing? – Karthik Dec 12 '18 at 18:46
  • Look at what `a[0]`, `a[0][:]`, etc do. Pay attention to the shapes, and changes if any. Remember `numpy` is running in Python. `[:]` isn't just a place holder in the larger expression. – hpaulj Dec 12 '18 at 20:14

1 Answers1

1

You misunderstand how numpy interprets the indexing/slicing. With something like a[x, y, z], numpy uses x to select along the first diminesion, y along the second dimension, and z along the third dimension.

However, with something like a[x][y][z], numpy uses x along the first dimension of a, it uses y along the first dimension of a[x], and z along the first dimension of a[x][y].

This can be confusing if you compare using : to using some number. Why is this the case? One means slicing (:), the other is indexing (no :). Because slicing along the dimension (using :) doesn't actually reduce the dimensions of your array whereas indexing does.

Could have a lot of examples to represent this, but I think it's best for you to go play in ipython with an array and see how different indexing and slicing affects the output. However, I'll provide an example or two specifically to answer your question

import numpy as np

a = np.arange(2*3*4).reshape((2,3,4))

a
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]]])

# First indexing notation
print(a[:, 0, 0].shape, a[0, :, 0].shape, a[0, 0, :].shape)
# Prints (2,) (3,), (4,)

Breaking this down, we take each one:

  • a[:, 0, 0] Takes all of the first dimension, and the 0th element for the second and third dimensions.
  • a[0, :, 0] Takes the 0th element of the first dimension, all of the second dimension, and the 0th element of the third dimension.
  • a[0, 0, :] Takes the 0th elements for the first and second dimensions and all of the elements for the third dimension.

# Second indexing notation
print(a[:][0][0].shape, a[0][:][0].shape, a[0][0][:].shape)
# Prints (4,) (4,) (4,)

In this case:

  • a[:] is basically the same as a (returns a new view of the matrix -- google "numpy view" for more info). Since a[:] is the same as a, a[:][0] selects the 0the element along the first dimension of a
  • etc...

OP said:

According the the numpy documentation, specifying array indices as array_name[x, y] and array_name[x][y] are equivalent

This is true! The major thing to recognize is that (although related) indexing and slicing are not the same thing (as I've pointed out above).

Stephen C
  • 1,966
  • 1
  • 16
  • 30