I know how to take x[:,:,:,:,j,:]
(which takes the jth slice of dimension 4).
Is there a way to do the same thing if the dimension is known at runtime, and is not a known constant?
I know how to take x[:,:,:,:,j,:]
(which takes the jth slice of dimension 4).
Is there a way to do the same thing if the dimension is known at runtime, and is not a known constant?
One option to do so is to construct the slicing programatically:
slicing = (slice(None),) * 4 + (j,) + (slice(None),)
An alternative is to use numpy.take()
or ndarray.take()
:
>>> a = numpy.array([[1, 2], [3, 4]])
>>> a.take((1,), axis=0)
array([[3, 4]])
>>> a.take((1,), axis=1)
array([[2],
[4]])
You can use the slice function and call it with the appropriate variable list during runtime as follows:
# Store the variables that represent the slice in a list/tuple
# Make a slice with the unzipped tuple using the slice() command
# Use the slice on your array
Example:
>>> from numpy import *
>>> a = (1, 2, 3)
>>> b = arange(27).reshape(3, 3, 3)
>>> s = slice(*a)
>>> b[s]
array([[[ 9, 10, 11],
[12, 13, 14],
[15, 16, 17]]])
This is the same as:
>>> b[1:2:3]
array([[[ 9, 10, 11],
[12, 13, 14],
[15, 16, 17]]])
Finally, the equivalent of not specifying anything between 2 :
in the usual notation is to put None
in those places in the tuple you create.
If everything is decided at runtime, you could do:
# Define the data (this could be measured at runtime)
data_shape = (3, 5, 7, 11, 13)
print('data_shape = {}'.format(data_shape))
# Pick which index to slice from which dimension (could also be decided at runtime)
slice_dim = len(data_shape)/2
slice_index = data_shape[slice_dim]/2
print('slice_dim = {} (data_shape[{}] = {}), slice_index = {}'.format(slice_dim, slice_dim, data_shape[slice_dim], slice_index))
# Make a data set for testing
data = arange(product(data_shape)).reshape(*data_shape)
# Slice the data
s = [slice_index if a == slice_dim else slice(None) for a in range(len(data_shape))]
d = data[s]
print('shape(data[s]) = {}, s = {}'.format(shape(d), s))
Although this is longer than ndarray.take()
, it will work if slice_index = None
, as in the case where the array happens to have so few dimensions that you don't actually want to slice it (but you don't know you don't want to slice it ahead of time).
You can also use ellipsis to replace the repeating colons. See an answer to How do you use the ellipsis slicing syntax in Python? for an example.