如何有效地将数组切片为重叠的子数组,以便
>>> N = 5
>>> L = 2 # could be any, less than N
>>> x = range(N)
预期结果是
[[1,0],[2,1],[3,2],[4,3]]
这是我尝试过的:
>>> [ x[i:i-L:-1] for i in range(L-1,len(x)) ]
[[], [3, 2], [4, 3], [5, 4]] # wrong
>>> [ x[i:i-L:-1] for i in range(L,len(x)) ]
[[2, 1], [3, 2], [4, 3]] # wrong
>>> [ x[i:i-L if i-L >= 0 else None:-1] for i in range(L-1,len(x)) ]
[[1, 0], [2, 1], [3, 2], [4, 3]] # correct
它产生了预期的结果,但它是实现它的最佳方式吗?
是否有一些可能有帮助的numpy,itertools函数?
答案 0 :(得分:1)
您可以使用简单列表理解
>>> [[x[i+1], x[i]] for i in range(len(x) - 1)]
[[1, 0], [2, 1], [3, 2], [4, 3]]
或使用itertools.izip
:
>>> from itertools import izip
>>> [list(k) for k in izip(x[1:], x)]
[[1, 0], [2, 1], [3, 2], [4, 3]]
我看到您更新了问题,因此使用itertools.izip
,itertools.islice
和itertools.imap
itertools
方式
>>> res = imap(lambda i:islice(reversed(x), i, i+L), xrange(N-L,-1,-1))
>>> [list(e) for e in res]
[[1, 0], [2, 1], [3, 2], [4, 3]]
甚至是纯粹的发电机:
>>> res = (reversed(x[i:i+L]) for i in xrange(N-L+1))
>>> [list(e) for e in res]
[[1, 0], [2, 1], [3, 2], [4, 3]]
答案 1 :(得分:1)
我假设输入为NumPy数组。所以,如果它还没有,我们可以把它作为一个np.asarray()
的数组。因此,如果输入是列表,我们将从:x = np.asarray(input_list)
开始。所以,随着设置让我们尝试解决问题。
这是一种使用strides
的方法,它使用views
的概念,避免制作副本,因此必须非常有效 -
L = 2 # Row length
strided = np.lib.stride_tricks.as_strided
n = x.strides[0]
out = strided(x[L-1:],shape=(x.size-L+1,L),strides=(n,-n))
样品运行 -
In [85]: L = 2
In [86]: strided(x[L-1:],shape=(x.size-L+1,L),strides=(n,-n))
Out[86]:
array([[1, 0],
[2, 1],
[3, 2],
[4, 3]])
In [87]: L = 3
In [88]: strided(x[L-1:],shape=(x.size-L+1,L),strides=(n,-n))
Out[88]:
array([[2, 1, 0],
[3, 2, 1],
[4, 3, 2]])
In [89]: L = 4
In [90]: strided(x[L-1:],shape=(x.size-L+1,L),strides=(n,-n))
Out[90]:
array([[3, 2, 1, 0],
[4, 3, 2, 1]])
这是使用broadcasting
-
L = 2 # Row length
out = x[np.arange(x.size-L+1)[:,None] + np.arange(L-1,-1,-1)]
答案 2 :(得分:1)
或使用常规zip(生成元组列表)
In [158]: x=list(range(5))
In [159]: x[1:],x[0:-1]
Out[159]: ([1, 2, 3, 4], [0, 1, 2, 3])
In [160]: list(zip(x[1:],x[0:-1]))
Out[160]: [(1, 0), (2, 1), (3, 2), (4, 3)]
或列表
In [161]: [list(i) for i in zip(x[1:],x[0:-1])]
Out[161]: [[1, 0], [2, 1], [3, 2], [4, 3]]
这是使用zip是一种转置。 numpy
数组也很容易转换:
In [167]: arr=np.array((x[1:],x[:-1]))
In [168]: arr
Out[168]:
array([[1, 2, 3, 4],
[0, 1, 2, 3]])
In [169]: arr.T.tolist()
Out[169]: [[1, 0], [2, 1], [3, 2], [4, 3]]
请注意,我必须制作两份清单。 Divakar的stride_tricks
方法是创建重叠窗口的唯一方法。没有复制。这是一种更先进的方法。
对于小型列表,我建议坚持使用列表方法。与创建数组相关的开销。