Python 如何通过切片范围有效地索引到一维numpy数组

Python 如何通过切片范围有效地索引到一维numpy数组,python,arrays,numpy,slice,Python,Arrays,Numpy,Slice,我有一个大的一维数据数组。我有一个开始索引数组,索引到发生重要事件的数据中。我想得到一个范围数组,这样我就可以得到长度为L的窗口,在开始时的每个起始点都有一个窗口。虚假样本数据: data = np.linspace(0,10,50) starts = np.array([0,10,21]) length = 5 我想本能地做一些事情,比如 data[starts:starts+length] 但实际上,我需要将开始转换为范围“窗口”的2D数组。从函数语言开始,我会将其视为从列表到列表的映射

我有一个大的一维数据数组。我有一个
开始
索引数组,索引到发生重要事件的数据中。我想得到一个范围数组,这样我就可以得到长度为
L
的窗口,在
开始时的每个起始点都有一个窗口。虚假样本数据:

data = np.linspace(0,10,50)
starts = np.array([0,10,21])
length = 5
我想本能地做一些事情,比如

data[starts:starts+length]
但实际上,我需要将
开始
转换为范围“窗口”的2D数组。从函数语言开始,我会将其视为从列表到列表的
映射,如:

np.apply_along_axis(lambda i: np.arange(i,i+length), 0, starts)
但这不起作用,因为
apply\u沿轴
只允许标量返回值

您可以这样做:

pairs = np.vstack([starts, starts + length]).T
ranges = np.apply_along_axis(lambda p: np.arange(*p), 1, pairs)
data[ranges]
或者,您也可以使用列表:

data[np.array([np.arange(i,i+length) for i in starts])]
或者你可以迭代地做。(呜呜)

有没有一种简洁、惯用的方法可以在这样的起点切入数组?(请原谅我这个新手的愚蠢。)

要实现这一点,您可以使用
NumPy.meshgrid()
,如下所述

正如hpaulj在评论中指出的,这个问题实际上不需要网格,因为可以使用阵列广播

返回

array([[ 0.        ,  0.20408163,  0.40816327,  0.6122449 ,  0.81632653],
       [ 2.04081633,  2.24489796,  2.44897959,  2.65306122,  2.85714286],
       [ 4.28571429,  4.48979592,  4.69387755,  4.89795918,  5.10204082]])

如果需要花费大量时间,可以使用
as_stried()
来创建
数据的滑动窗口数组

data = np.linspace(0,10,50000)
length = 5
starts = np.random.randint(0, len(data)-length, 10000)

from numpy.lib.stride_tricks import as_strided
sliding_window = as_strided(data, (len(data) - length + 1, length), 
                 (data.itemsize, data.itemsize))
然后您可以使用:

sliding_window[starts]
得到你想要的


它也比创建索引数组快。

注意:这与问题不同-该问题的长度不规则。在这里,我所做的应该适合普通的矩形数组。很好的一个,+1从我这里——据我所知,这是最简洁优雅的方法。
index=np.arange(length)+start[:,None]
也works@hpaulj啊!那要平滑得多。更新答案。
data = np.linspace(0,10,50000)
length = 5
starts = np.random.randint(0, len(data)-length, 10000)

from numpy.lib.stride_tricks import as_strided
sliding_window = as_strided(data, (len(data) - length + 1, length), 
                 (data.itemsize, data.itemsize))
sliding_window[starts]