In [205]: arr = np.array([
...: [0, 1, 2],
...: [3, 4, 5],
...: [6, 7, 8],
...: ])
...:
...: arr[ : , [0, 2] ]
Out[205]:
array([[0, 2],
[3, 5],
[6, 8]])
The array indexing does what we expect. It's just the base
that's different.
In [206]: _.base
Out[206]:
array([[0, 3, 6],
[2, 5, 8]])
I think this base
gives clues as to the underlying process of the indexing. It made a copy with the [0,2]
advanced indexing, and performed some sort of transpose to return the desired array.
I haven't paid whole lot of attention to base
. If there's doubt about whether something is a view or not, I like to compare the __array_interface__
.
Usually it's enough to know that the data
value is clearly different (and not just an offset).
In [209]: arr.__array_interface__
Out[209]:
{'data': (38026368, False),
'strides': None,
'descr': [('', '<i8')],
'typestr': '<i8',
'shape': (3, 3),
'version': 3}
In [210]: arr[ : , [0, 2] ].__array_interface__
Out[210]:
{'data': (38386288, False),
'strides': (8, 24),
'descr': [('', '<i8')],
'typestr': '<i8',
'shape': (3, 2),
'version': 3}
Looking further at the strides
:
In [218]: arr.strides
Out[218]: (24, 8)
In [219]: arr[:,[0,2]].strides
Out[219]: (8, 24)
In [220]: arr[:,[0,2]].copy().strides
Out[220]: (16, 8)
arr
strides is (3*8, 8)
, since stepping to the next row means skipping 3 column values. But the indexed strides are reversed, which is what I'd expect from the transpose of its base
. The full copy is (2*8,8)
reflecting the 2 column shape.
So here base
is revealing details of the indexing process. I haven't noticed those before, and I've been using numpy
for quite some time.
Another case where base
reflects the construction process, is making your arr
via arange
:
In [213]: np.arange(9).reshape(3,3).base
Out[213]: array([0, 1, 2, 3, 4, 5, 6, 7, 8])
That base
comes from the arange
, yet we never assigned to a variable.