将numpy数组的排列转换为ndarray或矩阵

3
foo = np.array([1,2,3,4])

我有一个名为foo的numpy数组,我想将其转换成一个类似于ndarry或矩阵的形式,如下所示:

bar = np.array([[1,2,3,4],[2,3,4,1],[3,4,1,2],[4,1,2,3]])

任何对于如何高效地完成此操作的建议?因为我的源数组 foo 的大小会发生变化,而我需要进行数百万次的转换。

你尝试过已发布的解决方案吗? - Divakar
3个回答

3

你可以在循环中使用np.roll

x = np.array([np.roll(foo, -x) for x in np.arange(foo.shape[0])])

print(x)
array([[1, 2, 3, 4],
       [2, 3, 4, 1],
       [3, 4, 1, 2],
       [4, 1, 2, 3]])

3
为了获得更高的性能,我们可以在这里使用 strides。关键是将原始数组与以第二个最后一个元素结束的切片数组连接起来,然后采用与原始数组长度相同的滑动窗口长度进行处理。
因此,实现方式如下 -
def strided_method(ar):
    a = np.concatenate(( ar, ar[:-1] ))
    L = len(ar)
    n = a.strides[0]
    return np.lib.stride_tricks.as_strided(a, (L,L), (n,n), writeable=False)

输出将是只读的,是连接数组的视图,因此几乎不受数组大小影响,具有恒定的时间。这意味着它是一个非常高效的解决方案。如果您需要具有自己内存空间的可写输出,请像后面的时间表中所示那样进行复制。
示例运行 -
In [51]: foo = np.array([1,2,3,4])

In [52]: strided_method(foo)
Out[52]: 
array([[1, 2, 3, 4],
       [2, 3, 4, 1],
       [3, 4, 1, 2],
       [4, 1, 2, 3]])

运行时测试 -

In [53]: foo = np.random.randint(0,9,(1000))

# @cᴏʟᴅsᴘᴇᴇᴅ's loopy soln
In [54]: %timeit np.array([np.roll(foo, -x) for x in np.arange(foo.shape[0])])
100 loops, best of 3: 12.7 ms per loop

In [55]: %timeit strided_method(foo)
100000 loops, best of 3: 7.46 µs per loop

In [56]: %timeit strided_method(foo).copy()
1000 loops, best of 3: 454 µs per loop

1
在等你发帖! - cs95

2
这些矩阵被称为汉克尔矩阵。大多数平台已经提供了创建它们的特定程序。您也可以通过删除不必要的部分来自己实现,以增加速度。这是相当简洁的代码
from scipy.linalg import hankel

A = hankel([1,2,3,4], [4,1,2,3])
A
array([[1, 2, 3, 4],
       [2, 3, 4, 1],
       [3, 4, 1, 2],
       [4, 1, 2, 3]])

看起来它只比Divakar的解决方案慢大约2倍,这是出乎意料的快速。


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