从一个1D numpy数组中高效地切片窗口,围绕第二个2D数组给出的索引

2024-04-20 09:25:51 发布

您现在位置:Python中文网/ 问答频道 /正文

我想从同一个1D numpy数组中提取多个切片,切片索引是从随机分布中提取的。基本上,我想实现以下目标:

import numpy as np
import numpy.random

# generate some 1D data
data = np.random.randn(500)

# window size (slices are 2*winsize long)
winsize = 60

# number of slices to take from the data
inds_size = (100, 200)

# get random integers that function as indices into the data
inds = np.random.randint(low=winsize, high=len(data)-winsize, size=inds_size)

# now I want to extract slices of data, running from inds[0,0]-60 to inds[0,0]+60
sliced_data = np.zeros( (winsize*2,) + inds_size )
for k in range(inds_size[0]):
    for l in range(inds_size[1]):
        sliced_data[:,k,l] = data[inds[k,l]-winsize:inds[k,l]+winsize]

# sliced_data.shape is now (120, 100, 200)

上面的嵌套循环工作正常,但是非常慢。我需要的数组比实际的数据大上千倍。有没有什么方法可以更有效地做到这一点?在

注意,inds在我的例子中始终是2D的,但是在得到切片之后,我将始终对这两个维度中的一个进行求和,因此只在一维上累积和的方法是可以的。在

我发现this question和{a2}看起来几乎相同。然而,问题只是关于一维索引向量(而不是我的2D)。另外,这个答案缺少一点上下文,因为我不太理解建议的as_strided是如何工作的。因为我的问题似乎并不少见,我想我应该再问一次,希望得到一个更具解释性的答案,而不仅仅是代码。在


Tags: oftoimportnumpydatasizeasnp
2条回答

下面是一个使用^{}-

# Get 3D offsetting array and add to inds for all indices
allinds = inds + np.arange(-60,60)[:,None,None]

# Index into data with all indices for desired output
sliced_dataout = data[allinds]

运行时测试-

^{pr2}$

内存消耗:折衷解决方案

如果内存消耗是一个问题,这里有一个折衷的解决方案-

sliced_dataout = np.zeros( (winsize*2,) + inds_size )
for k in range(sliced_data.shape[0]):
    sliced_dataout[k] = data[inds-winsize+k] 

以这种方式使用as_strided似乎比Divakar的方法(这里是20毫秒对35毫秒)快一些,尽管内存使用可能是个问题。在

data_wins = as_strided(data, shape=(data.size - 2*winsize + 1, 2*winsize), strides=(8, 8))
inds = np.random.randint(low=0, high=data.size - 2*winsize, size=inds_size)
sliced = data_wins[inds]
sliced = sliced.transpose((2, 0, 1))    # to use the same index order as before

Strides是每个维度中索引的步骤(以字节为单位)。例如,对于shape (x, y, z)的数组和大小为d(float64为8)的数据类型时,跨距通常为(y*z*d, z*d, d),因此第二个索引跨过z项的整行。将这两个值都设置为8,data_wins[i, j]data_wins[j, i]将引用相同的内存位置。在

^{pr2}$

相关问题 更多 >