I have a ND numpy array (let say for instance 3x3x3) from wich I'd like to extract a sub-array, combining slices and index arrays. For instance:
import numpy as np
A = np.arange(3*3*3).reshape((3,3,3))
i0, i1, i2 = ([0,1], [0,1,2], [0,2])
ind1 = j0, j1, j2 = np.ix_(i0, i1, i2)
ind2 = (j0, slice(None), j2)
B1 = A[ind1]
B2 = A[ind2]
I would expect that B1 == B2, but actually, the shapes are different
>>> B1.shape
(2, 3, 2)
>>> B2.shape
(2, 1, 2, 3)
>>> B1
array([[[ 0, 2],
[ 3, 5],
[ 6, 8]],
[[ 9, 11],
[12, 14],
[15, 17]]])
>>> B2
array([[[[ 0, 3, 6],
[ 2, 5, 8]]],
[[[ 9, 12, 15],
[11, 14, 17]]]])
Someone understands why? Any idea of how I could get 'B1' by manipulating only 'A' and 'ind2' objects? The goal is that it would work for any nD arrays, and that I would not have to look for the shape of dimensions I want to keep entirely (hope I'm clear enough:)). Thanks!!
---EDIT---
To be clearer, I would like to have a function 'fun' such that
A[fun(ind2)] == B1
The indexing subspaces of
ind1
are (2,),(3,),(2,), and the resultingB
is(2,3,2)
. This is a simple case of advanced indexing.ind2
is a case of (advanced) partial indexing. There are 2 indexed arrays, and 1 slice. The advanced indexing documentation states:In this case advanced indexing constructs a
(2,2)
array (from the 1st and 3rd indexes), and appends the slice dimension at the end, resulting in a(2,2,3)
array.I explain the reasoning in more detail in https://stackoverflow.com/a/27097133/901925
A way to fix a tuple like
ind2
, is to expand each slice into an array. I recently saw this done innp.insert
.expands
:
to[0,1,2]
. But the replacement has to have the right shape.I'm leaving off the details of determining which term is a slice, its dimension, and the relevant reshape. The goal is to reproduce
i1
.If indices were generated by something other than
ix_
, reshaping this slice could be more difficult. For exampleThe expanded slice has to be compatible with the other arrays under broadcasting.
Swapping axes after indexing is another option. The logic, though, might be more complex. But in some cases transposing might actually be simpler:
This is the closer I can get to your specs, I haven't been able to devise a solution that can compute the correct indices without knowing
A
(or, more precisely, its shape...).A shorter version
In restricted indexing cases like this using
ix_
, it is possible to do the indexing in successive steps.is the same as
and since
i2
is the full range,If you only have
ind2
availableIn more general contexts you have to know how
j0,j1,j2
broadcast with each other, but when they are generated byix_
, the relationship is simple.I can imagine circumstances in which it would be convenient to assign
A1 = A[i1]
, followed by a variety of actions involvingA1
, including, but not limited toA1[...,i3]
. You have to be aware of whenA1
is a view, and when it is a copy.Another indexing tool is
take
: