给定形状为(n, m)
的ndarray ar
,我想沿着长度为k
的轴1用k<m
提取子序列。在长度为k
的子序列的已知起始索引start
的情况下,这可以用new_ar = ar[:, start:end]
(或仅用start:start+k
)来解决。
但是,如果我有一个列表start_list
和一个长度为n
的end_list
(或者只有start_list
,因为子序列的长度无论如何都是已知的),它包含我想要提取的子序列的开始索引(和结束索引),该怎么办?直觉上,我尝试了ar[:, start_list:end_list]
,但这会抛出TypeError: slice indices must be integers or None or have an __index__ method
。
如果不使用循环并利用NumPys方法,这个问题**会有什么解决方案?对于我的问题,for循环花了30分钟,但这必须有一个NumPy风格的5ms解决方案,因为它只是索引。
[编辑]:由于使用代码可能会更好地理解问题(谢谢您的提示),我将尝试使其更紧凑,并通过循环显示我为解决问题所做的工作。
我有一个形状为(40450, 200000)
的ndarray,代表每个长度为200000
的40450
信号。信号发生了变化,我想让它们对齐。所以我想从每个40450
序列中提取长度为190000
的子序列。为此,我有一个长度为40450
的列表start_list
,包含子序列的起始索引(我要提取的每个40450
子序列在长度为200000
的原始序列中具有不同的起点)。
我可以使用for循环来解决这个问题(ar
包含原始序列,start_list
包含起始索引):
k = 190000
ar_new = np.zeros((40450, k))
for i in range(ar_new.shape[0]):
ar_new[i] = ar[i, start_list[i]:start_list[i]+k]
例如,如果start_list[0]
是0
,这意味着我需要ar[0, 0:190000]
,如果start_list[10000]
是1337
,这意味着我需要ar[10000, 1337:1337+190000]
等等。
但对于我的情况,这需要超过30分钟,我相信通过NumPy内置方法/一些切片魔法可以以某种方式解决它。
2条答案
按热度按时间wmvff8tz1#
在经历了一些考验之后
我在想①如果你可以没有非对齐的数据,覆盖看起来更快②无论如何,如果进程包含在内存中,我希望我的结果在1?10秒的范围内,而不是30分钟③如果你的问题是交换,覆盖避免分配大约
4*4E4*2E5 ⇒ 32E9
字节的内存。mspsb9vt2#
我们可以将原始的2维阵列视为3维结构。在
as_strided
的帮助下,我们可以创建数组的3D视图,其中第一个维度等于原始维度,第二个维度用于迭代子行的可能开始位置,第三个维度用于迭代子行中的值:另见: