【问题标题】:Split list into separate but overlapping chunks将列表拆分为单独但重叠的块
【发布时间】:2016-11-04 22:12:54
【问题描述】:

假设我有一个列表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[2,3,4],以此类推。

我相信numpy中有一个函数可以进行这种操作。

【问题讨论】:

  • 那么你按照什么规则来分割一个列表呢?用填充分成 3 组?请明确。
  • 这里我的窗口大小是 3.,即每个拆分列表应该有 3 个元素首先拆分 [1,2,3] 并且步长是 2 ,所以第二个拆分开始应该从第三个元素开始,第二个拆分是[3,4,5] 分别。
  • 请将其添加到您的问题中,这是清楚的。你自己有没有尝试过解决这个问题?
  • 好的,我将使用我尝试过的代码编辑我的问题。

标签: python list


【解决方案1】:

只需使用 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]]

但您必须编写几行代码以确保您的代码不会因前所未有的大小/步长值而中断。

【讨论】:

  • 另一个列表表达式是list( zip( *[x[i::2] for i in range(3)]))
【解决方案2】:

“重复”Partition array into N chunks with Numpy 建议 np.split - 这对于不重叠的拆分很好。该示例(在关闭之后添加?)重叠,每个子数组中有一个元素。加上它用 0 填充。

How do you split a list into evenly sized chunks? 有一些很好的列表答案,有各种形式的生成器或列表理解,但乍一看,我没有看到任何允许重叠的东西——尽管巧妙地使用了迭代器(例如 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 pad。

选择目标shape 很简单,5 组,每组 3 组。选择跨步需要更多关于跨步的知识。

In [69]: x.strides
Out[69]: (4,)

1d 跨步,或从一个元素步进到下一个元素,为 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]

【讨论】:

  • 如果您要重新打开基于 cmets 的问题,至少然后编辑问题以包含该额外信息。我现在已经重新关闭了这个问题,目前还不清楚。
  • @Martijn 我得到了答案。请打开这个问题。它对其他人有用。
【解决方案3】:

我写的这个函数可能对你有帮助,虽然它只输出长度为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]

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-12-14
    • 2018-05-17
    • 2017-05-20
    • 2021-03-11
    • 2017-11-02
    • 1970-01-01
    • 2016-11-14
    相关资源
    最近更新 更多