您可以定义一个产生生成器的函数并使用它。窗口将是您要除以2的形状的底面,技巧是在沿行和列移动时仅沿该窗口索引数组。
def window(arr, shape=(3, 3)): # Find row and column window sizes r_win = np.floor(shape[0] / 2).astype(int) c_win = np.floor(shape[1] / 2).astype(int) x, y = arr.shape for i in range(x): xmin = max(0, i - r_win) xmax = min(x, i + r_win + 1) for j in range(y): ymin = max(0, j - c_win) ymax = min(y, j + c_win + 1) yield arr[xmin:xmax, ymin:ymax]
您可以这样使用此功能:
arr = np.array([[1,2,3,4], [2,3,4,5], [3,4,5,6], [4,5,6,7]])gen = window(arr)next(gen)array([[1, 2], [2, 3]])
通过生成器将生成示例中的所有窗口。
它没有向量化,但是我不确定是否有一个现有的向量化函数可以返回不同大小的数组。正如@PaulPanzer指出的那样,您可以将数组填充到所需的大小,然后使用
np.lib.stride_tricks.as_strided生成切片的视图。像这样:
def rolling_window(a, shape): s = (a.shape[0] - shape[0] + 1,) + (a.shape[1] - shape[1] + 1,) + shape strides = a.strides + a.strides return np.lib.stride_tricks.as_strided(a, shape=s, strides=strides)def window2(arr, shape=(3, 3)): r_extra = np.floor(shape[0] / 2).astype(int) c_extra = np.floor(shape[1] / 2).astype(int) out = np.empty((arr.shape[0] + 2 * r_extra, arr.shape[1] + 2 * c_extra)) out[:] = np.nan out[r_extra:-r_extra, c_extra:-c_extra] = arr view = rolling_window(out, shape) return viewwindow2(arr, (3,3))array([[[[ nan, nan, nan], [ nan, 1., 2.], [ nan, 2., 3.]], [[ nan, nan, nan], [ 1., 2., 3.], [ 2., 3., 4.]], [[ nan, nan, nan], [ 2., 3., 4.], [ 3., 4., 5.]], [[ nan, nan, nan], [ 3., 4., nan], [ 4., 5., nan]]], [[[ nan, 1., 2.], [ nan, 2., 3.], [ nan, 3., 4.]], [[ 1., 2., 3.], [ 2., 3., 4.], [ 3., 4., 5.]], [[ 2., 3., 4.], [ 3., 4., 5.], [ 4., 5., 6.]], [[ 3., 4., nan], [ 4., 5., nan], [ 5., 6., nan]]], [[[ nan, 2., 3.], [ nan, 3., 4.], [ nan, 4., 5.]], [[ 2., 3., 4.], [ 3., 4., 5.], [ 4., 5., 6.]], [[ 3., 4., 5.], [ 4., 5., 6.], [ 5., 6., 7.]], [[ 4., 5., nan], [ 5., 6., nan], [ 6., 7., nan]]], [[[ nan, 3., 4.], [ nan, 4., 5.], [ nan, nan, nan]], [[ 3., 4., 5.], [ 4., 5., 6.], [ nan, nan, nan]], [[ 4., 5., 6.], [ 5., 6., 7.], [ nan, nan, nan]], [[ 5., 6., nan], [ 6., 7., nan], [ nan, nan, nan]]]])
此版本使用边缘填充,
np.nan以避免与数组中的任何其他值混淆。给定的数组比
window函数快大约3倍,但是我不确定填充输出对您要在下游执行的操作有何影响。



