我需要根据给定切片条件的三个值(aa
)对数组(N1, N2, N3
)进行切片,如下所示:
import numpy as np
N1, N2, N3 = 200, 500000, 30
aa = np.random.uniform(0., 1., N1*N2)
bb = []
for i in range(N1):
bb += list(aa[i * N2:(i * N2) + N3])
此代码遵循以下规则生成新数组bb
:
N3
的前aa
个元素N2
元素并添加N3
的以下aa
元素aa
用尽我可以通过numpy索引更快地执行此过程吗?
答案 0 :(得分:3)
仅需重塑为2D
并切片前N3列-
bb = aa.reshape(N1,N2)[:,:N3].ravel()
当N3
超过N2
如果N3
超过N2
,则这些aa[i * N2:(i * N2) + N3]
在迭代中会重叠。为了解决这种情况,我们可以创建滑动窗口,然后切片行,直到我们有足够的长度,然后为剩余的窗口创建一个循环-
from skimage.util.shape import view_as_windows
starts = np.arange(len(aa), step=N2)
lens = len(aa) - np.arange(len(aa), step=N2)
rem_lens = lens[lens < N3]
m0 = lens < N3
l1 = N3*(~m0).sum()
l2 = rem_lens.sum()
out = np.empty(l1+l2, dtype=aa.dtype)
out[:l1] = view_as_windows(aa,(N3))[::N2].ravel()
rem_starts = starts[m0]
ss = l1+np.r_[0,rem_lens.cumsum()]
for s,i,j in zip(rem_starts, ss[:-1], ss[1:]):
out[i:j] = aa[s:]
答案 1 :(得分:2)
您可以通过重塑数组来更优雅地完成此操作。首先将初始数组设为2D:
N1, N2, N3 = 200, 500000, 30
aa = np.random.uniform(0., 1., (N1, N2))
现在,只需在第二维上删除大小为N3
的块即可:
bb = aa[:, :N3]
如果您需要bb
使其平坦,请使其平坦
bb = aa[:, :N3].ravel()
答案 2 :(得分:0)
您可以使用NumPy的array_split
或split
来更简单地完成相同的事情。
但是,效率可能不会显着提高。
使用aa[i * N2:(i * N2) + N3]
存储一堆数组切片是切片数量的线性时间。在NumPy内执行该循环(因此,假设您使用的是CPython,则在C循环而不是Python循环中执行)会更快一些。但是,除非您有大量的切片,否则可能没关系。
但是,使用list(aa[i * N2:(i * N2) + N3])
将每个分片转换为列表,然后扩展现有列表非常慢。这可能要花费您总时间的99%以上,因此优化其他1%的问题是无关紧要的。 NumPy无法做任何加速将每个片段转换为列表的事情。
因此,如果您实际上不需要列表,只需停止调用list
。您可以只使用数组列表,并根据需要chain
一起使用它们,也可以在数组列表中构建a custom-strided array,也可以ravel
将原始数组变成形状你想要的。
如果您要做需要一个列表,这从本质上来说很慢,而且您无能为力。