由于您在每个位置的索引未对齐,因此您可以创建一个掩码或花哨的索引来提取所需的元素。由于提取的值将是平坦的,因此您必须重新调整它们。
以下是创建蒙版的方法:
K = 50
mask = np.zeros((M, N, P + 1), dtype=np.int8)
np.put_along_axis(mask, array2, 1, axis=-1)
np.put_along_axis(mask, array2 + K, -1, axis=-1)
mask.cumsum(axis=-1, out=mask)
mask = mask[..., :-1].view(bool)
我们使用np.int8
和np.bool_
具有相同项目大小的事实,并将np.cumsum
初始掩码位置传播到每个轴的最终位置。
其余的相当容易:
array3 = array1[mask].reshape(M, N, K)
在构造掩码时,您可以通过绕过np.put_along_axis
并在适当的情况下使用带有剪辑的直接索引来避免额外的元素:
mask = np.zeros_like(array1, dtype=np.int8)
r = np.tile(np.arange(M)[:, None, None], (1, N, 1))
c = np.tile(np.arange(N)[None, :, None], (M, 1, 1))
clip_mask = array2 + K < P
mask[r, c, array2] = 1
mask[r[clip_mask], c[clip_mask], array2[clip_mask] + K] = -1
mask = np.cumsum(mask, axis=-1, out=mask).view(bool)
这一切都非常浪费:要获得一个 shape 数组(M, N, K)
,您要创建一个大小为布尔掩码,(M, N, P)
以及一些大小为索引数组(M, N, 1)
,另一个大小为掩码,(M, N, 1)
然后是这些索引数组的一些掩码版本。在这里使用for
循环确实没有什么问题,只要您编译它们,例如使用 cython 或 numba。