我有一个二维数组,我需要将部分(切片)提取到一个新数组中:
original= numpy.ndarray( shape=(4,4) )
slices= numpy.ndarray( shape=(0,2) )
for x in range(3):
slice= original[x:x+2,x:x+2]
slices=numpy.append(slices, slice,axis=0)
有没有更有效的方法来做到这一点(摆脱python循环)?
---- ---- EDIT
为了澄清,我问如何将任意(但类似)形状的2D切片从2D阵列的任意2D索引复制到另一个,垂直堆叠 - 特别是沿对角线或2x2大小。
答案 0 :(得分:3)
stride_tricks
有一个漂亮的技巧,你可以在SO和其他方面找到具有不同通用性的滚动窗口函数(目前numpy本身没有),这里是根据你所得到的版本:
def rolling_window(arr, window):
"""Very basic multi dimensional rolling window. window should be the shape of
of the desired subarrays. Window is either a scalar or a tuple of same size
as `arr.shape`.
"""
shape = np.array(arr.shape*2)
strides = np.array(arr.strides*2)
window = np.asarray(window)
shape[arr.ndim:] = window # new dimensions size
shape[:arr.ndim] -= window - 1
if np.any(shape < 1):
raise ValueError('window size is too large')
return np.lib.stride_tricks.as_strided(arr, shape=shape, strides=strides)
# Now:
view = rolling_window(arr, 2)
view[0,0] # first slice in your loop
请注意view
保存与原始数组相同的数据!这可能会导致意外结果。但是你似乎只想要对角线,你可以用大步技巧来做到这一点,以确保你不需要复制数据(下一版本将创建一个diagonal
的视图,旧版本总是一个副本):
diagonal = np.diagonal(view, axis1=0, axis2=1)
# unfortunatly now the first slice is diagonal[...,0], so just roll it to the start:
diagonal = np.rollaxis(diagonal, -1)
现在diagonal
是您在for循环中创建的数组(如果您不想查看,则在较新版本上添加.copy()
。)
编辑:由于slices
数组是2D而不是3D因为你追加,所以这里缺少一个重塑:
slices = diagonal.reshape(-1,2)
如果你有这么小的数组,但是它的常量(期望在diagonal
调用中复制数据)与数组大小相比,这可能不会更快。
答案 1 :(得分:1)
以下是您的解决方案:
v = np.arange(0,original.shape[0],0.5).astype(int)
result = np.c_[ original[v[1:-1],v[:-2]] , original[v[1:-1],v[2:]] ]
适用于任何大小的方形输入矩阵(您称之为“原始”)。
这个想法是创建一个“辅助数组”v,它只是[0,0,1,1,2,2,3,3,...],然后使用你需要的指数观察总是简单的v。
切片享受!