Нарезка массива numpy вдоль динамически заданной оси
Я хотел бы динамически отрезать массив numpy вдоль определенной оси. Учитывая это:
axis = 2
start = 5
end = 10
Я хочу добиться того же результата, что и:
# m is some matrix
m[:,:,5:10]
Используя что-то вроде этого:
slc = tuple(:,) * len(m.shape)
slc[axis] = slice(start,end)
m[slc]
Но значения :
не могут быть помещены в кортеж, поэтому я не могу понять, как построить срез.
Ответы
Ответ 1
Я думаю, что одним из способов было бы использовать slice(None)
:
>>> m = np.arange(2*3*5).reshape((2,3,5))
>>> axis, start, end = 2, 1, 3
>>> target = m[:, :, 1:3]
>>> target
array([[[ 1, 2],
[ 6, 7],
[11, 12]],
[[16, 17],
[21, 22],
[26, 27]]])
>>> slc = [slice(None)] * len(m.shape)
>>> slc[axis] = slice(start, end)
>>> np.allclose(m[slc], target)
True
У меня есть смутное чувство, что раньше я использовал функцию для этого, но теперь я не могу найти его.
Ответ 2
Как было сказано недостаточно ясно (и я тоже искал):
эквивалент:
a = my_array[:, :, :, 8]
b = my_array[:, :, :, 2:7]
является:
a = my_array.take(indices=8, axis=3)
b = my_array.take(indices=range(2, 7), axis=3)
Ответ 3
Это немного поздно для вечеринки, но Numpy по умолчанию делает это numpy.take
. Однако тот всегда копирует данные (так как он поддерживает необычную индексацию, он всегда предполагает, что это возможно). Чтобы избежать этого (во многих случаях вам понадобится просмотр данных, а не их копии), воспользуйтесь опцией slice(None)
, уже упомянутой в другом ответе, возможно, обернув ее в приятную функцию:
def simple_slice(arr, inds, axis):
# this does the same as np.take() except only supports simple slicing, not
# advanced indexing, and thus is much faster
sl = [slice(None)] * arr.ndim
sl[axis] = inds
return arr[tuple(sl)]
Ответ 4
Существует элегантный способ доступа к произвольной оси n
массива x
: используйте numpy.moveaxis
¹, чтобы переместить интересующую ось вперед.
x_move = np.moveaxis(x, n, 0) # move n-th axis to front
x_move[start:end] # access n-th axis
Подвох в том, что вам, вероятно, придется применить moveaxis
к другим массивам, которые вы используете с выводом x_move[start:end]
, чтобы сохранить согласованность порядка осей. Массив x_move
является только видом, поэтому каждое изменение, которое вы вносите в его переднюю ось, соответствует изменению x
на оси n
-th (то есть вы можете читать/записывать в x_move
).
1) Вы также можете использовать свапы, чтобы не беспокоиться о порядке n
и 0
, в отличие от moveaxis(x, n, 0)
. Я предпочитаю moveaxis
, чем swapaxes
, потому что это только меняет порядок относительно n