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)]
answer_dms
Warning (from warnings module):
File "C:\Users\leland.hepworth\test_dynamic_slicing.py", line 7
return a[slc]
FutureWarning: Using a non-tuple sequence for multidimensional indexing is
deprecated; use `arr[tuple(seq)]` instead of `arr[seq]`. In the future this will be
interpreted as an array index, `arr[np.array(seq)]`, which will result either in an
error or a different result.
correct: True
time: 2.2048302
method: in_place
answer_smiglo
correct: True
time: 5.9013344
method: copy
answer_eelkespaak
correct: True
time: 1.1219435999999998
method: in_place
answer_clemisch
correct: True
time: 13.707583699999999
method: in_place
answer_leland
correct: True
time: 0.9781496999999995
method: in_place
x_move = np.moveaxis(x, n, 0) # move n-th axis to front
x_move[start:end] # access n-th axis
问题是你可能需要在其他数组上使用moveaxis来保持轴顺序的一致性,因为x_move数组只是一个视图,所以你对它的前一个轴所做的每一个改变都对应着x在第n个轴上的改变(也就是说你可以读/写x_move)。 1)与moveaxis(x, n, 0)相反,您也可以使用swapaxes来不用担心n和0的顺序,我更喜欢moveaxis而不是swapaxes,因为它只改变了n的顺序。
from numpy import *
def slicer(a, axis=None, slices=None):
if not hasattr(axis, '__iter__'):
axis = [axis]
if not hasattr(slices, '__iter__') or len(slices) != len(axis):
slices = [slices]
slices = [ sl if isinstance(sl,slice) else slice(*sl) for sl in slices ]
mask = []
fixed_axis = array(axis) % a.ndim
case = dict(zip(fixed_axis, slices))
for dim, size in enumerate(a.shape):
mask.append( case[dim] if dim in fixed_axis else slice(None) )
return a[tuple(mask)]
它适用于可变数量的轴,并以切片元组作为输入
>>> a = array( range(10**4) ).reshape(10,10,10,10)
>>> slicer( a, -2, (1,3) ).shape
(10, 10, 2, 10)
>>> slicer( a, axis=(-1,-2,0), slices=((3,), s_[:5], slice(3,None)) ).shape
(7, 10, 5, 3)
一个稍微紧凑的版本
def slicer2(a, axis=None, slices=None):
ensure_iter = lambda l: l if hasattr(l, '__iter__') else [l]
axis = array(ensure_iter(axis)) % a.ndim
if len(ensure_iter(slices)) != len(axis):
slices = [slices]
slice_selector = dict(zip(axis, [ sl if isinstance(sl,slice) else slice(*sl) for sl in ensure_iter(slices) ]))
element = lambda dim_: slice_selector[dim_] if dim_ in slice_selector.keys() else slice(None)
return a[( element(dim) for dim in range(a.ndim) )]
def _slice_along_axis(slice_inds,axis=-1):
'''
Returns a slice such that the 1d slice provided by slice_inds, slices along the dimension provided.
'''
from_end=False
if axis<0: # choosing axis at the end
from_end = True
axis = -1-axis
explicit_inds_slice = axis*(slice(None),)
if from_end:
return (Ellipsis,slice_inds) + explicit_inds_slice
else:
return explicit_inds_slice + (slice_inds,)
为了使用这个函数,你可以像往常一样简单地调用切片。
a = my_array[:, :, :, 8]
b = my_array[:, :, :, 2:7]
c = my_array[...,3] # (equivalent to my_array.take(axis=-1,indices=3)
相当于
a = my_array[_slice_along_axis(8,axis=3)]
b = my_array[_slice_along_axis(slice(2,7),axis=3)]
c = my_array[_slice_along_axis(3,axis=-1)]
7条答案
按热度按时间rhfm7lfc1#
因为它没有被提到足够清楚(我也在寻找它):
a相当于:
是:
vatpfxk52#
我认为一种方法是使用
slice(None)
:我有一种模糊的感觉,我以前用过一个函数,但现在似乎找不到了。
zbsbpyhn3#
这有点晚了,但是Numpy的默认方法是
numpy.take
。(因为它支持花哨的索引,所以它总是假设这是可能的)。(在许多情况下,您需要的是数据的 * 视图 *,而不是副本),回退到另一个答案中已经提到的slice(None)
选项,可能用一个很好的函数来 Package 它zaq34kh64#
这是 * 非常 * 晚的聚会,但我有一个替代切片函数,执行比其他答案稍好:
下面是测试每个答案的代码,每个版本都标有发布答案的用户名:
以下是结果:
np.take
的Śmigło's answer会产生更差的结果,并且虽然它不是仅查看,但它确实会创建副本。np.moveaxis
的clemisch's answer需要最长的时间才能完成,但令人惊讶的是,它会引用回前一个数组的内存位置。我还为每个版本添加了一个
step
参数,以防您需要。vvppvyoh5#
有一种优雅的方法可以访问数组
x
的任意轴n
:使用numpy.moveaxis
¹将感兴趣的轴移到前面。问题是你可能需要在其他数组上使用
moveaxis
来保持轴顺序的一致性,因为x_move
数组只是一个视图,所以你对它的前一个轴所做的每一个改变都对应着x
在第n
个轴上的改变(也就是说你可以读/写x_move
)。1)与
moveaxis(x, n, 0)
相反,您也可以使用swapaxes
来不用担心n
和0
的顺序,我更喜欢moveaxis
而不是swapaxes
,因为它只改变了n
的顺序。whhtz7ly6#
这确实是非常非常晚了!但是我得到了Leland's answer并对其进行了扩展,这样它就可以使用多个轴和切片参数。
它适用于可变数量的轴,并以切片元组作为输入
一个稍微紧凑的版本
4dbbbstv7#
我没有看到任何关于
Ellipsis
对象的注解,所以想包含另一个稍微不同的解决方案,它适用于正轴和负轴。这个解决方案有一个函数,可以沿着所需的维度生成切片。我包含这个的主要原因是为了确保学习动态切片的人也学习使用省略号。
为了使用这个函数,你可以像往常一样简单地调用切片。
相当于
这种方法的一个优点是,切片可以生成一次,然后在其他数组中使用,即使其他数组中的维数不相同(负轴的情况)。