10

I'm a bit confused about the indexing of numpy. Assume the following example:

>>> import numpy as np
>>> x = np.arange(10)
>>> x.shape = (2,5)
>>> x
array([[0, 1, 2, 3, 4],
       [5, 6, 7, 8, 9]])
>>> x[0:-1]
array([[0, 1, 2, 3, 4]])
>>> x[1:-1]
array([], shape=(0, 5), dtype=int64)
>>> x[1:]
array([[5, 6, 7, 8, 9]])

What I'm confused about, I can get the first row as 2D-array using x[0:-1]. But what does the -1 actually means in terms of indices? I would have thought, that calling x[1:-1] would then give me the second row, but instead if returns me an empty array, and to get what I want I need to use x[1:]?

I'm a little bit confused. Thanks for the help

kmario23
  • 57,311
  • 13
  • 161
  • 150
Ragadabing
  • 472
  • 2
  • 7
  • 14
  • 1
    `[1:-1]`: from the second (item/row) to the last (=second) item/row: that will lead to an empty array. – 9769953 Jan 07 '19 at 15:45
  • Try first with a simple Python list of two elements: `x = [1, 2]`, and index that in the same way: see what you get. It just so happens in your case, that the numbers `1` and `2` are replaced by arrays of length 5. – 9769953 Jan 07 '19 at 15:46

2 Answers2

10

You have this statement:

In [31]: x[0:-1]

This way of indexing means that "start at 1st row and go till the last row (excluded)". That's why we get the first row as a result.

Out[31]: array([[0, 1, 2, 3, 4]])

But, when you do:

 In [31]: x[1:-1]   
 Out[31]: array([], shape=(0, 5), dtype=int64)

It's asking NumPy to "start at second row and not include the last row". Since here the second row is also the last row, it is excluded and we get an empty array as a result.


More information: There's nothing specific about using negative indexing such as -1 here. For instance, the following ways of indexing would also return empty arrays.

# asking to "start at first row and end at first row"
In [42]: x[0:0]  
Out[42]: array([], shape=(0, 5), dtype=int64)

# asking to "start at second row and end at second row"
In [43]: x[1:1]  
Out[43]: array([], shape=(0, 5), dtype=int64)

When it comes to indexing in Python/NumPy, it's always "left inclusive and right exclusive".

Here's something in plain Python (i.e. indexing a list)

In [52]: lst = [1, 2] 

In [53]: lst[1:-1]    
Out[53]: []   # an empty list

Please note the construct of indexing which is: [start:stop:step]

If we start and stop at the same index, then we get nowhere and an empty data structure (array/list/tuple etc.) is returned as a result.

kmario23
  • 57,311
  • 13
  • 161
  • 150
2

If you request a slice x[a:b], you will receive a section spanning from a up to but not including b. So if you slice x[1:-1], the resulting array will not include -1, which happens to be the same as 1 in a (2,5) array. Another example:

>>> import numpy as np
>>> x = np.arange(15)
>>> x.shape = (3,5)
>>> x
array([[0,  1,  2,  3,  4],
       [5,  6,  7,  8,  9],
       [10, 11, 12, 13, 14]])
>>> x[0:-1]
array([[0, 1, 2, 3, 4],
       [5, 6, 7, 8, 9]])
>>> x[1:-1]
array([[5, 6, 7, 8, 9]])

The last operation above slices x from row 1 up to (not including) the last row, which is just row 1.

MPA
  • 1,878
  • 2
  • 26
  • 51