slicing an n-dimensional array

classic Classic list List threaded Threaded
5 messages Options
Reply | Threaded
Open this post in threaded view
|

slicing an n-dimensional array

Moroney, Catherine M (388D)
Hello,

I'm sure there's a simple solution, but I'm not seeing it so any hints would be
greatly appreciated.

I have an array "A" of shape (NX, NY, NZ), and then I have a second array "B" of shape (NX, NY)
that ranges from 0 to NZ in value.

I want to create a third array "C" of shape (NX, NY) that holds the "B"-th slice for each (NX, NY).

For example:

A = numpy.zeros((NX,NY,NZ))
A[:,:,0] = numpy.arange(0, NX*NY).reshape(NX,NY)
A[:,:,1] = numpy.arange(1, NX*NY+1).reshape(NX,NY)

and so on

B = numpy.zeros((NX,NY))
B[0,0] = 0
B[0,1] = 1

so C[0,0] = A[0,0,B[0,0]]
   C[0,1] = A[0,1,B[0,1]]
   ...
   C[NX-1,NY-1] = A[NX-1,NY-1,B[NX-1,NY-1]]

   and C has shape(NX,NY)

How do I accomplish this without loops?

Thank-you for any advice,

Catherine
_______________________________________________
NumPy-Discussion mailing list
[hidden email]
http://mail.scipy.org/mailman/listinfo/numpy-discussion
Reply | Threaded
Open this post in threaded view
|

Re: slicing an n-dimensional array

Stéfan van der Walt
Hi Catherine

On 2014-12-04 01:12:30, Moroney, Catherine M (398E) <[hidden email]> wrote:
> I have an array "A" of shape (NX, NY, NZ), and then I have a second array "B" of shape (NX, NY)
> that ranges from 0 to NZ in value.
>
> I want to create a third array "C" of shape (NX, NY) that holds the
> "B"-th slice for each (NX, NY)

Those two arrays can broadcast if you expand the dimensions of B:

A: (NX, NY, NZ)
B: (NX, NY, 1)

Your result would be

B = B[..., np.newaxis]  # now shape (NX, NY, 1)
C = A[B]

For more information on this type of broadcasting manipulation, see

http://nbviewer.ipython.org/github/stefanv/teaching/blob/master/2014_assp_split_numpy/numpy_advanced.ipynb

and

http://wiki.scipy.org/EricsBroadcastingDoc

Stéfan
_______________________________________________
NumPy-Discussion mailing list
[hidden email]
http://mail.scipy.org/mailman/listinfo/numpy-discussion
Reply | Threaded
Open this post in threaded view
|

Re: slicing an n-dimensional array

Benjamin Root-2
Posting in the correct thread now...

A slightly different way to look at it (I don't think it is exactly the same problem, but the description reminded me of it):
http://mail.scipy.org/pipermail/numpy-discussion/2013-April/066269.html
(and I think there are some things that can be done to make that faster, but I don't recall it right now)

Ben Root

On Wed, Dec 3, 2014 at 7:02 PM, Stefan van der Walt <[hidden email]> wrote:
Hi Catherine

On 2014-12-04 01:12:30, Moroney, Catherine M (398E) <[hidden email]> wrote:
> I have an array "A" of shape (NX, NY, NZ), and then I have a second array "B" of shape (NX, NY)
> that ranges from 0 to NZ in value.
>
> I want to create a third array "C" of shape (NX, NY) that holds the
> "B"-th slice for each (NX, NY)

Those two arrays can broadcast if you expand the dimensions of B:

A: (NX, NY, NZ)
B: (NX, NY, 1)

Your result would be

B = B[..., np.newaxis]  # now shape (NX, NY, 1)
C = A[B]

For more information on this type of broadcasting manipulation, see

http://nbviewer.ipython.org/github/stefanv/teaching/blob/master/2014_assp_split_numpy/numpy_advanced.ipynb

and

http://wiki.scipy.org/EricsBroadcastingDoc

Stéfan
_______________________________________________
NumPy-Discussion mailing list
[hidden email]
http://mail.scipy.org/mailman/listinfo/numpy-discussion


_______________________________________________
NumPy-Discussion mailing list
[hidden email]
http://mail.scipy.org/mailman/listinfo/numpy-discussion
Reply | Threaded
Open this post in threaded view
|

Re: slicing an n-dimensional array

Jaime Fernández del Río
In reply to this post by Stéfan van der Walt
On Wed, Dec 3, 2014 at 4:02 PM, Stefan van der Walt <[hidden email]> wrote:
Hi Catherine

On 2014-12-04 01:12:30, Moroney, Catherine M (398E) <[hidden email]> wrote:
> I have an array "A" of shape (NX, NY, NZ), and then I have a second array "B" of shape (NX, NY)
> that ranges from 0 to NZ in value.
>
> I want to create a third array "C" of shape (NX, NY) that holds the
> "B"-th slice for each (NX, NY)

Those two arrays can broadcast if you expand the dimensions of B:

A: (NX, NY, NZ)
B: (NX, NY, 1)

Your result would be

B = B[..., np.newaxis]  # now shape (NX, NY, 1)
C = A[B]

For more information on this type of broadcasting manipulation, see

http://nbviewer.ipython.org/github/stefanv/teaching/blob/master/2014_assp_split_numpy/numpy_advanced.ipynb

and

http://wiki.scipy.org/EricsBroadcastingDoc


I don't think this would quite work... Even though it now has 3 dimensions (Nx, Ny, 1), B is still a single array, so when fancy indexing A with it, it will only be applied to the first axis, so the return will be of shape B.shape + A.shape[1:], that is (Nx, Ny, 1, Ny, Nz).

What you need to have is three indexing arrays, one per dimension of A, that together broadcast to the desired shape of the output C. For this particular case, you could do:

nx = np.arange(A.shape[0])[:, np.newaxis]
ny = np.arange(A.shape[1])
C = A[nx, ny, B]

To show that this works:

>>> A = np.arange(2*3*4).reshape(2, 3, 4)
>>> A
array([[[ 0,  1,  2,  3],
        [ 4,  5,  6,  7],
        [ 8,  9, 10, 11]],

       [[12, 13, 14, 15],
        [16, 17, 18, 19],
        [20, 21, 22, 23]]])
>>> B = np.random.randint(4, size=(2, 3))
>>> B
array([[2, 1, 2],
       [2, 0, 3]])
>>> nx = np.arange(A.shape[0])[:, None]
>>> ny = np.arange(A.shape[1])
>>> A[nx, ny, B]
array([[ 2,  5, 10],
       [14, 16, 23]])

Jaime

--
(\__/)
( O.o)
( > <) Este es Conejo. Copia a Conejo en tu firma y ayúdale en sus planes de dominación mundial.

_______________________________________________
NumPy-Discussion mailing list
[hidden email]
http://mail.scipy.org/mailman/listinfo/numpy-discussion
Reply | Threaded
Open this post in threaded view
|

Re: slicing an n-dimensional array

Stéfan van der Walt
On 2014-12-04 03:41:35, Jaime Fernández del Río <[hidden email]> wrote:
> nx = np.arange(A.shape[0])[:, np.newaxis]
> ny = np.arange(A.shape[1])
> C = A[nx, ny, B]

That's the correct answer--in my answer I essentially wrote

C = A[B] (== A[B, :, :])

which broadcasts the shape of B against the second and third dimensions
of A (it's almost always a bad idea to combine index broadcasting
and slicing).

The notes I linked to are correct, though, and explain Jamie's answer in
more detail (search for "Jack's Dilemma").

Regards
Stéfan
_______________________________________________
NumPy-Discussion mailing list
[hidden email]
http://mail.scipy.org/mailman/listinfo/numpy-discussion