3

In Numpy, can we use a 2D array as index into a 1D array? What array array indexing rule applies to following code?

# 1D array
arr = np.arange(10)
# array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])

# 2D index 
indx = np.array([[2, 4], [6, 8]])

# 2D index in 1D array
arr[indx]

# Output of above indexing is a 2D array!
array([[2, 4],[6, 8]])
Vadim Kotov
  • 8,084
  • 8
  • 48
  • 62
Saurabhp75
  • 31
  • 5
  • Can you clarify exactly what you mean? The code you posted works correctly, and yes you can use a 2D array to index a 1D array. – user3483203 Mar 12 '18 at 07:53
  • I couldn't find the rule in numpy documentation, can you point me to relevant documentation where this type of indexing is discussed. I know this works, but i want to understand why. – Saurabhp75 Mar 12 '18 at 07:57
  • From [the docs](https://docs.scipy.org/doc/numpy-1.13.0/user/basics.indexing.html#single-element-indexing): "_Unlike lists and tuples, numpy arrays support multidimensional indexing for multidimensional arrays._" but it's not so clear how it's done. – user2314737 Mar 12 '18 at 08:05
  • This is exactly what i want to understand. From experimenting one can see that, one can use N dimensional array to index a 1D array. The output will be an N dimensional array, provided the index are within the bounds of 1D array. – Saurabhp75 Mar 12 '18 at 08:13
  • I'm pretty sure you can have as index an array of any size and shape as long as its elements are valid indexes of the original array (in this case integers 0..9) – user2314737 Mar 12 '18 at 08:22

1 Answers1

1

What array array indexing rule applies to following code?

That's how numpy's advanced indexing works. The shape of result array is related to shape of index array, the array's shape and the axis you're passing the index. Here are some examples that passes a 3D array as index to the first axis of arrays with different shapes.

In [47]: a.shape
Out[47]: (2, 5)

In [48]: b = a[np.array([[[0],[1]],[[1],[1]]])]

In [49]: b.shape
Out[49]: (2, 2, 1, 5)

In [50]: arr.shape
Out[50]: (3, 3, 3)

In [51]: b = arr[np.array([[[0],[1]],[[1],[1]]])]

In [52]: b.shape
Out[52]: (2, 2, 1, 3, 3)

And here is what you get when you pass different arrays to different axises:

In [61]: b = arr[[[0],[2]],[[1],[0]]]

In [62]: b.shape
Out[62]: (2, 1, 3)

In [63]: arr.shape
Out[63]: (3, 3, 3)

In all of these indexings, Numpy will check multiple things, first off, it checks the type of the objects passed as index. Secondly, it compares the shapes of your index array with the shape of respective axis of your array. Thirdly, it checks if the result produces a valid Numpy array.

Here are some other examples:

In [64]: b = arr[[[[0],[2]]],[[1],[0]]]

In [65]: b.shape
Out[65]: (1, 2, 1, 3)

In [66]: b
Out[66]: 
array([[[[ 3,  4,  5]],

        [[18, 19, 20]]]])

In [67]: b = arr[[[[0],[2]]],[1],[0]]

In [68]: b
Out[68]: 
array([[[ 3],
        [21]]])

In [69]: b = arr[[[['a'],[2]]],[1],[0]]
---------------------------------------------------------------------------
IndexError                                Traceback (most recent call last)
<ipython-input-69-dba030ba9787> in <module>()
----> 1 b = arr[[[['a'],[2]]],[1],[0]]

IndexError: only integers, slices (`:`), ellipsis (`...`), numpy.newaxis (`None`) and integer or boolean arrays are valid indices

In [70]: b = arr[[[[0],[2]]],[1],0]

In [71]: b = arr[[[[0],[2]]],[5],0]
---------------------------------------------------------------------------
IndexError                                Traceback (most recent call last)
<ipython-input-71-0962012e570a> in <module>()
----> 1 b = arr[[[[0],[2]]],[5],0]

IndexError: index 5 is out of bounds for axis 1 with size 3

In [72]: 

In [72]: b = arr[[[[0],[[2]]]],[5],0]
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-72-9a520b0cb30e> in <module>()
----> 1 b = arr[[[[0],[[2]]]],[5],0]

ValueError: setting an array element with a sequence.

In [73]: b = arr[[[[0],[[2]]]],[5],[0]]
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-73-67187db6f452> in <module>()
----> 1 b = arr[[[[0],[[2]]]],[5],[0]]

ValueError: setting an array element with a sequence.
Mazdak
  • 105,000
  • 18
  • 159
  • 188
  • Thanks, what I can conclude from above is that, as long as index array elements are within the bounds of the array to be indexed, we get a valid output. The shape of the output is the shape of the indexed array with the axis on which it was indexed, replaced by the shape of index array. For eg. index array shape , indx = (x1, x2, ...xn) , shape of array to be indexed, arr = (y1, y2....ym). Shape of output with indx array on axis 'k' of arr = (y1, y2... yk-1, x1, x2, .., xn, ..yk, yk+1.,,,ym). – Saurabhp75 Mar 12 '18 at 09:06
  • @user8579809 Kind of but not completely. You cannot determine the result's shape simply like that because there are multiple cases and they'll generate results based on multiple rules (but similar though). – Mazdak Mar 12 '18 at 09:16
  • 1
    The best way to figure this out is to just play with different arrays and indexes in different shapes. – Mazdak Mar 12 '18 at 09:18
  • I used this to assign a 1D array with 2D array index... It's works too., but I don't know why... – Joao_PS Apr 17 '23 at 14:50