2017-10-21 160 views
3
foo = np.array([1,2,3,4]) 

我有一个numpy的阵列foo,我想变换成一个ndarry或矩阵,类似于:排列置换一个numpy的阵列的成ndarray或矩阵

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

如何任何建议要有效地做到这一点,因为我的源数组foo的大小会有所不同,而且我需要将此转换数百万次。

+0

发布的解决方案是否适合您? – Divakar

回答

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

正在等你发帖! –

2

这些矩阵称为汉克尔矩阵。大多数平台都提供了创建它们的特定例程。您也可以通过删除不必要的部分来提高速度来实现自己。这是a pretty concise code

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]]) 

看来,这只是〜2倍比Divakar的解决方案,它是出奇的快慢。