Śmigło
Śmigło

Reputation: 1047

Multi dimensional array slice in one object

I have a numpy array:

arr = numpy.arange(25 * 10 * 20)
arr.resize((25, 10, 20))

I want to get slice like this:

arr[3:6, 2:8, 7:9]

This works:

index = [slice(3, 6), slice(2, 8), slice(7, 9)]
arr[index]

But this doesn't:

>>> index = slice([3, 2, 7], [6, 8, 9])
>>> arr[index]
TypeError: slice indices must be integers or None or have an __index__ method

Can it be done by ONE slice object? Or only list of 3 slices will work?

Upvotes: 4

Views: 2745

Answers (5)

denis
denis

Reputation: 21947

Is np.s_, "A nicer way to build up index tuples for arrays", what you want ?

A = np.arange( 25 * 10 * 20 ).reshape( 25, 10, 20 )

region = np.s_[ 3:6, 2:8, 7:9 ]
# (slice(3, 6, None), slice(2, 8, None), slice(7, 9, None))

A[region]  # your arr[slices], shape (3, 6, 2)

(would be nice if the doc for np.s_ had such an example, not just 1d.)

Upvotes: 0

David Wesby
David Wesby

Reputation: 749

Can it be done by ONE slice object?

No, slice objects are one-dimensional.

Or only list of 3 slices will work?

A list of 3 slices will not work as of v1.23.0. Multidimensional indexing with non-tuple values has been deprecated since v1.15 and expired in v1.23.0 (see this section of the changelog).

As of v1.23.0, the only way to specify a multidimensional slice with a single object is to use a tuple of slice objects. If you would like to use [:] notation, you can create a tuple of slice objects using numpy.s_. In OP's case:

>>> numpy.s_[3:6, 2:8, 7:9]
(slice(3, 6, None), slice(2, 8, None), slice(7, 9, None))

Upvotes: 1

B. M.
B. M.

Reputation: 18668

you can use numpy.ogrid:

  a[ogrid[3:6, 2:8, 7:9]]

select you block.

Upvotes: 1

grovina
grovina

Reputation: 3077

You can create a list of slices, zipping the two lists of indices:

>>> slices = [slice(*i) for i in zip([3,2,7], [6,8,9])]
>>> arr[slices]
array([[[ 647,  648],
    [ 667,  668],
    [ 687,  688],
    [ 707,  708],
    [ 727,  728],
    [ 747,  748]],

   [[ 847,  848],
    [ 867,  868],
    [ 887,  888],
    [ 907,  908],
    [ 927,  928],
    [ 947,  948]],

   [[1047, 1048],
    [1067, 1068],
    [1087, 1088],
    [1107, 1108],
    [1127, 1128],
    [1147, 1148]]])

Check with numpy.array_equal:

>>> numpy.array_equal(arr[slices], arr[3:6,2:8,7:9])
True

Upvotes: 1

Kinght 金
Kinght 金

Reputation: 18341

>>> help(slice)
class slice(object)
 |  slice(stop)
 |  slice(start, stop[, step])

So we use slice(start, stop, step)

>>> import numpy as np
>>> x = np.arange(10)

## ERROR

>>> i=slice([1,3])
>>> x[i]
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: slice indices must be integers or None or have an __index__ method

## OK

>>> i = slice(3,7,2)
>>> print(x)
[0 1 2 3 4 5 6 7 8 9]
>>> print(i)
slice(3, 7, 2)
>>> print(x[i])
[3 5]

For multi dimensional:

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

Upvotes: 1

Related Questions