Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Differences in using range() or slice() to slice a 2-d ndarray

When I try to learn how slice() works, I came across some interesting results when using range() vs. slice(). I don't know how to explain the mechanism. Any help will be appreciated.

For example: given an np array:

a = np.array(range(100)).reshape(10,10)

a[slice(0,10,2)] and a[range(0,10,2)] are identical.

however,

a[(slice(0,10,2),slice(0,10,2))] 

is

[[0,2...],[20,22...],[40,42,44]...]

but

a[(range(0,10,2),range(0,10,2))] 

is

[0,22,44,66...]

Can anyone explain this?

like image 653
shubow Avatar asked Aug 22 '26 23:08

shubow


1 Answers

Indexing with a range and indexing with a slice are, in general, two very different things. You happened upon a case that gives equal results, although note, the slice version creates a view of the underlying buffer, whereas indexing with the range objects creates a new underlying buffer.

So note:

>>> a = np.array(range(100)).reshape(10,10)
>>> s = a[slice(0,10,2)]
>>> r = a[range(0,10,2)]
>>> a[0,0] = 1000
>>> a
array([[1000,    1,    2,    3,    4,    5,    6,    7,    8,    9],
       [  10,   11,   12,   13,   14,   15,   16,   17,   18,   19],
       [  20,   21,   22,   23,   24,   25,   26,   27,   28,   29],
       [  30,   31,   32,   33,   34,   35,   36,   37,   38,   39],
       [  40,   41,   42,   43,   44,   45,   46,   47,   48,   49],
       [  50,   51,   52,   53,   54,   55,   56,   57,   58,   59],
       [  60,   61,   62,   63,   64,   65,   66,   67,   68,   69],
       [  70,   71,   72,   73,   74,   75,   76,   77,   78,   79],
       [  80,   81,   82,   83,   84,   85,   86,   87,   88,   89],
       [  90,   91,   92,   93,   94,   95,   96,   97,   98,   99]])
>>> s
array([[1000,    1,    2,    3,    4,    5,    6,    7,    8,    9],
       [  20,   21,   22,   23,   24,   25,   26,   27,   28,   29],
       [  40,   41,   42,   43,   44,   45,   46,   47,   48,   49],
       [  60,   61,   62,   63,   64,   65,   66,   67,   68,   69],
       [  80,   81,   82,   83,   84,   85,   86,   87,   88,   89]])
>>> r
array([[ 0,  1,  2,  3,  4,  5,  6,  7,  8,  9],
       [20, 21, 22, 23, 24, 25, 26, 27, 28, 29],
       [40, 41, 42, 43, 44, 45, 46, 47, 48, 49],
       [60, 61, 62, 63, 64, 65, 66, 67, 68, 69],
       [80, 81, 82, 83, 84, 85, 86, 87, 88, 89]])

When you use a slice, well, you are going to get slice semantics. The range object is treated as a sequence of indices. This triggers advanced indexing behavior

So from the documentation:

When the index consists of as many integer arrays as the array being indexed has dimensions, the indexing is straight forward, but different from slicing.

so, ARR[[x1, x2, ..., xn], [y1, y2, ..., yn]] will give you something like

[ARR[x1,y1], ARR[x2,y2], ... ARR[xn, yn]]

As @ShadowRanger notes in the comments, if you want the copy-semantics of using the range-indexing, you should still probably use a[:10:2,:10:2].copy() because it will be faster.

like image 174
juanpa.arrivillaga Avatar answered Aug 24 '26 12:08

juanpa.arrivillaga



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!