tags:

views:

87

answers:

3
+3  Q: 

Slicing at runtime

Hello,

can someone explain me how to slice a numpy.array at runtime? I don't know the rank (number of dimensions) at 'coding time'.

A minimal example:

import numpy as np
a = np.arange(16).reshape(4,4) # 2D matrix
targetsize = [2,3] # desired shape

b_correct = dynSlicing(a, targetsize)
b_wrong = np.resize(a, targetsize)

print a
[[ 0  1  2  3]
 [ 4  5  6  7]
 [ 8  9 10 11]
 [12 13 14 15]]
print b_correct
[[0 1 2]
 [4 5 6]]
print b_wrong
[[0 1 2]
 [3 4 5]]

And my ugly dynSlicing():

def dynSlicing(data, targetsize):
    ndims = len(targetsize)

    if(ndims==1):
        return data[:targetsize[0]],
    elif(ndims==2):
        return data[:targetsize[0], :targetsize[1]]
    elif(ndims==3):
        return data[:targetsize[0], :targetsize[1], :targetsize[2]]
    elif(ndims==4):
        return data[:targetsize[0], :targetsize[1], :targetsize[2], :targetsize[3]]

Resize() will not do the job since it flats the array before dropping elements.

Thanks, Tebas

+1  A: 

You can directly 'change' it. This is due to the nature of arrays only allowing backdrop.

Instead you can copy a section, or even better create a view of the desired shape: http://www.scipy.org/Tentative_NumPy_Tutorial#head-1529ae93dd5d431ffe3a1001a4ab1a394e70a5f2

Thomas Ahle
But how does this help?The question was about how to slice if the rank is not known at the time I write the code.Just looking for a fancy alternative for dynSlicing().
Tebas
+6  A: 

Passing a tuple of slice objects does the job:

def dynSlicing(data, targetsize):
    return data[tuple(slice(x) for x in targetsize)]
fortran
Yes, this is nice. Complexity is O(no_dims) and no data is copied :-)Thanks!
Tebas
you're welcome, it was just a matter of understanding what the `__getitem__` method was getting as argument :-)
fortran
@Tebas, thanks are nice, but you should _accept_ this good and useful answer (use the checkmark-shaped icon under the number on the answer's left) - that's crucial Stack-overflow etiquette!
Alex Martelli
+2  A: 

Simple solution:

b = a[tuple(map(slice,targetsize))]
Charles Beattie
I've marked +1 on Thomas and fortran
Charles Beattie
a little bit shorter, but it's slightly better to use a generator expression instead of map because the intermediate list isn't needed :-)
fortran