在NumPy数组中每隔n个元素进行子采样

148

我是一个numpy的初学者,我正在尝试从一个长的numpy数组中提取一些数据。我的需求是从数组中定义的位置开始,每隔n个数据点子采样,直到我的数组结束。

基本上,如果我有:

a = [1,2,3,4,1,2,3,4,1,2,3,4....] 

我想对这个进行子采样,从 a[1] 开始并每隔四个点采样一次,得到类似下面的结果

b = [2,2,2.....]
2个回答

241
您可以使用NumPy的切片,简单地使用start:stop:step
>>> xs
array([1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4])
>>> xs[1::4]
array([2, 2, 2])

这将创建原始数据的一个“视图”,因此它是“常数时间”。它还会反映对原始数组的更改,并在内存中保留整个原始数组。
>>> a
array([1, 2, 3, 4, 5])
>>> b = a[::2]         # O(1), constant time
>>> b[:] = 0           # modifying the view changes original array
>>> a                  # original array is modified
array([0, 2, 0, 4, 0])

所以,如果以上任何一项存在问题,您可以明确地复制:

>>> a
array([1, 2, 3, 4, 5])
>>> b = a[::2].copy()  # explicit copy, O(n)
>>> b[:] = 0           # modifying the copy
>>> a                  # original is intact
array([1, 2, 3, 4, 5])

这不是恒定时间,但结果与原始数组无关。复制品在内存中也是连续的,这可以使一些操作更快。

3
谢谢你提醒我关于引用/值复制的问题。否则我肯定会掉进陷阱里。 - F.S.
a[::2].copy() 解决了我的问题。当我将其作为numpy数组使用ctypes导入到C中时,仅使用a[::2]会得到几乎垃圾的结果(我的数组似乎从未被缩小)。如果我通过numpy.clip()运行它或在for循环中显式复制每个变量,这也是可以解决的。不确定这是否是一个错误。 - VSB

0

补充behzad.nouri的答案: 如果您想控制最终元素的数量并确保它始终固定为预定义值(而不是控制子样本之间的固定步长),则可以使用numpy的linspace方法,然后进行整数舍入。

例如,当num_elements=4时:

>>> a
array([1, 2, 3, 4, 5, 6, 7, 8, 9, 10])
>>> choice = np.round(np.linspace(1, len(a)-1, num=4)).astype(int)
>>> a[choice]
array([ 2,  5,  7, 10])

或者说,一般情况下,对于具有最终起始/结束点的数组进行子采样:

>>> import numpy as np
>>> np.round(np.linspace(0, len(a)-1, num=4)).astype(int)
array([0, 3, 6, 9])
>>> np.round(np.linspace(0, len(a)-1, num=15)).astype(int)
array([0, 1, 1, 2, 3, 3, 4, 4, 5, 6, 6, 7, 8, 8, 9])

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接