将列表拆分成独立但重叠的块

7

假设我有一个名为A的列表。

A = [1,2,3,4,5,6,7,8,9,10]

我希望创建一个新的列表(称为B),其顺序如下所示,基于上述列表。
B = [[1,2,3], [3,4,5], [5,6,7], [7,8,9], [9,10,]]

即取前三个数字作为A[0,1,2],后三个数字作为A[3,4,5]等。

我相信在numpy中有一种函数可以实现这样的操作。


那么,您按照什么规则拆分列表?每组包含3个元素并进行填充?请详细说明。 - Martijn Pieters
这里我的窗口大小是3,即每个分割列表应该有3个元素。第一个分割是 [1,2,3],步长为2,因此第二个分割应该从第3个元素开始,第二个分割分别是[3,4,5]。 - Rangooski
请将此内容添加到您的问题中,这一点并不清楚。您自己是否尝试过解决这个问题? - Martijn Pieters
好的,我会在我的问题中编辑我尝试过的代码。 - Rangooski
显示剩余3条评论
3个回答

14

使用Python内置的列表推导与切片即可实现:

>>> A = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
>>> size = 3
>>> step = 2
>>> A = [A[i : i + size] for i in range(0, len(A), step)]

这会给你想要的东西:

>>> A
[[1, 2, 3], [3, 4, 5], [5, 6, 7], [7, 8, 9], [9, 10]]

但你需要写几行代码来确保你的程序不会因为未曾预料到的size/step值而出错。


3
另一个列表表达式是 list( zip( *[x[i::2] for i in range(3)])) - hpaulj

12
“重复”使用Numpy将数组分成N个块建议使用np.split进行非重叠拆分。 该示例(在关闭后添加?)重叠,每个子数组跨越一个元素。此外,它用0填充。 如何将列表分成均匀大小的块?有一些很好的列表答案,具有各种形式的生成器或列表推导式,但乍一看,我没有看到任何允许重叠的方法-尽管通过巧妙地使用迭代器(例如iterator.tee),应该是可能的。
我们可以归咎于问题措辞不当,但它并不重复。
从示例和评论开始:

这里我的窗口大小为3,即每个拆分列表应具有3个元素,第一个拆分[1,2,3],步长为2,因此第二个拆分应从第3个元素开始,第二个拆分分别为[3,4,5]。

这是一个使用 as_strided 的高级解决方案。
In [64]: ast=np.lib.index_tricks.as_strided  # shorthand 

In [65]: A=np.arange(1,12)

In [66]: ast(A,shape=[5,3],strides=(8,4))
Out[66]: 
array([[ 1,  2,  3],
       [ 3,  4,  5],
       [ 5,  6,  7],
       [ 7,  8,  9],
       [ 9, 10, 11]])

我增加了 A 的范围,因为我不想处理 0 填充。
选择目标 shape 很容易,5 组 3。选择步幅需要更多有关步幅的知识。
In [69]: x.strides
Out[69]: (4,)

The 1d striding,即从一个元素到下一个的步长为4个字节(一个元素的长度)。从一行到下一行的步长是原始行的2个元素,或者2*4个字节。 as_strided生成一个视图。因此,在其中更改元素将影响原始数据,并可能更改重叠值。添加.copy()以进行复制;使用步幅数组进行数学运算也会产生副本。
更改步幅可以产生不重叠的行,但要注意形状-有可能访问原始数据缓冲区之外的值。
In [82]: ast(A,shape=[4,3],strides=(12,4))
Out[82]: 
array([[ 1,  2,  3],
       [ 4,  5,  6],
       [ 7,  8,  9],
       [10, 11, 17]])

In [84]: ast(A,shape=[3,3],strides=(16,4))
Out[84]: 
array([[ 1,  2,  3],
       [ 5,  6,  7],
       [ 9, 10, 11]])

编辑

新的功能提供了一个更安全的 as_strided 版本。

np.lib.strided_tricks.sliding_window_view(np.arange(1,10),3)[::2]

如果您要根据评论重新打开一个问题,那么至少编辑问题以包含额外信息。目前来看,问题不清楚,因此我已经重新关闭了它。 - Martijn Pieters
@Martijn 我得到了我的答案。请打开这个问题。它会对其他人有用。 - Rangooski
关于编辑:应该是 np.lib.stride_tricks,你多打了一个D。 - edoelas

1

我写的这个函数可能会对你有所帮助,尽管它只输出长度为 len_chunk 的填充块:

def overlap(array, len_chunk, len_sep=1):
    """Returns a matrix of all full overlapping chunks of the input `array`, with a chunk
    length of `len_chunk` and a separation length of `len_sep`. Begins with the first full
    chunk in the array. """

    n_arrays = np.int(np.ceil((array.size - len_chunk + 1) / len_sep))

    array_matrix = np.tile(array, n_arrays).reshape(n_arrays, -1)

    columns = np.array(((len_sep*np.arange(0, n_arrays)).reshape(n_arrays, -1) + np.tile(
        np.arange(0, len_chunk), n_arrays).reshape(n_arrays, -1)), dtype=np.intp)

    rows = np.array((np.arange(n_arrays).reshape(n_arrays, -1) + np.tile(
        np.zeros(len_chunk), n_arrays).reshape(n_arrays, -1)), dtype=np.intp)
        
    return array_matrix[rows, columns]

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