从 numpy 数组中以步长 m 切片 n 个元素
Slicing n elements with stride m from numpy array
我想找到一种简洁的方法从 numpy 数组中以步长 m 对 n 个连续元素进行采样。最简单的情况是用 stride 2 采样 1 个元素,这意味着获取列表中的所有其他元素,可以这样完成:
>>> a = np.arange(10)
>>> a
array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
>>> a[::2]
array([0, 2, 4, 6, 8])
但是,如果我想以 m 步幅对 n 个连续元素进行切片,其中 n 和 m 可以是任何整数怎么办?例如,如果我想以 3 的步幅对 2 个连续的元素进行切片,我会得到这样的结果:
array([0, 1, 3, 4, 6, 7, 9])
是否有一种 Pythonic 和简洁的方法来做到这一点?谢谢!
这段代码可能会有用,我在问题中的例子(n=2,m=3)上进行了测试
import numpy as np
def get_slice(arr, n, m):
b = np.array([])
for i in range(0, len(arr), m):
b = np.concatenate((b, arr[i:i + n]))
return b
sliced_arr = get_slice(np.arange(10), n=2, m=3)
print(sliced_arr)
输出
[0. 1. 3. 4. 6. 7. 9.]
如果 a
足够长,您可以重塑、切片和拆开
a.reshape(-1,3)[:,:2].ravel()
但是a
必须是(9,)或(12,)。结果仍然是一个副本。
建议:
np.lib.stride_tricks.as_strided(a, (4,2), (8*3, 8)).ravel()[:-1]
也是副本。 as_strided
部分是一个视图,但 ravel
将制作一个副本。还有那个额外元素的丑陋。
sliding_window_view
添加为更安全的版本:
In [81]: np.lib.stride_tricks.sliding_window_view(a,(3))
Out[81]:
array([[0, 1, 2],
[1, 2, 3],
[2, 3, 4],
[3, 4, 5],
[4, 5, 6],
[5, 6, 7],
[6, 7, 8],
[7, 8, 9]])
In [82]: np.lib.stride_tricks.sliding_window_view(a,(3))[::3,:2]
Out[82]:
array([[0, 1],
[3, 4],
[6, 7]])
再次ravel
将进行复制。这省略了“额外” 9
.
np.resize
执行带填充的 reshape
(根据需要重复 a
):
In [83]: np.resize(a, (4,3))
Out[83]:
array([[0, 1, 2],
[3, 4, 5],
[6, 7, 8],
[9, 0, 1]])
In [84]: np.resize(a, (4,3))[:,:2]
Out[84]:
array([[0, 1],
[3, 4],
[6, 7],
[9, 0]])
我想找到一种简洁的方法从 numpy 数组中以步长 m 对 n 个连续元素进行采样。最简单的情况是用 stride 2 采样 1 个元素,这意味着获取列表中的所有其他元素,可以这样完成:
>>> a = np.arange(10)
>>> a
array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
>>> a[::2]
array([0, 2, 4, 6, 8])
但是,如果我想以 m 步幅对 n 个连续元素进行切片,其中 n 和 m 可以是任何整数怎么办?例如,如果我想以 3 的步幅对 2 个连续的元素进行切片,我会得到这样的结果:
array([0, 1, 3, 4, 6, 7, 9])
是否有一种 Pythonic 和简洁的方法来做到这一点?谢谢!
这段代码可能会有用,我在问题中的例子(n=2,m=3)上进行了测试
import numpy as np
def get_slice(arr, n, m):
b = np.array([])
for i in range(0, len(arr), m):
b = np.concatenate((b, arr[i:i + n]))
return b
sliced_arr = get_slice(np.arange(10), n=2, m=3)
print(sliced_arr)
输出
[0. 1. 3. 4. 6. 7. 9.]
如果 a
足够长,您可以重塑、切片和拆开
a.reshape(-1,3)[:,:2].ravel()
但是a
必须是(9,)或(12,)。结果仍然是一个副本。
建议:
np.lib.stride_tricks.as_strided(a, (4,2), (8*3, 8)).ravel()[:-1]
也是副本。 as_strided
部分是一个视图,但 ravel
将制作一个副本。还有那个额外元素的丑陋。
sliding_window_view
添加为更安全的版本:
In [81]: np.lib.stride_tricks.sliding_window_view(a,(3))
Out[81]:
array([[0, 1, 2],
[1, 2, 3],
[2, 3, 4],
[3, 4, 5],
[4, 5, 6],
[5, 6, 7],
[6, 7, 8],
[7, 8, 9]])
In [82]: np.lib.stride_tricks.sliding_window_view(a,(3))[::3,:2]
Out[82]:
array([[0, 1],
[3, 4],
[6, 7]])
再次ravel
将进行复制。这省略了“额外” 9
.
np.resize
执行带填充的 reshape
(根据需要重复 a
):
In [83]: np.resize(a, (4,3))
Out[83]:
array([[0, 1, 2],
[3, 4, 5],
[6, 7, 8],
[9, 0, 1]])
In [84]: np.resize(a, (4,3))[:,:2]
Out[84]:
array([[0, 1],
[3, 4],
[6, 7],
[9, 0]])