从向量创建矩阵,其中每一行都是向量的移位版本

发布于 2021-01-29 14:11:22

我有一个像这样的numpy数组

import numpy as np

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

我想创建一个看起来像这样的数组:

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

从而,每行对应于ar通过行索引+1移位的行。

一个简单的实现可能看起来像这样:

ar_roll = np.tile(ar, ar.shape[0]).reshape(ar.shape[0], ar.shape[0])

for indi, ri in enumerate(ar_roll):
    ar_roll[indi, :] = np.roll(ri, indi + 1)

这给了我想要的输出。

我的问题是,是否有更聪明的方法可以避免循环。

关注者
0
被浏览
124
1 个回答
  • 面试哥
    面试哥 2021-01-29
    为面试而生,有面试问题,就找面试哥。

    这是一种方法NumPy strides,该方法主要使用剩余元素填充,然后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-1:], (L,L), (-n,n))
    

    样品运行-

    In [42]: ar = np.array([1, 2, 3, 4])
    
    In [43]: strided_method(ar)
    Out[43]: 
    array([[4, 1, 2, 3],
           [3, 4, 1, 2],
           [2, 3, 4, 1],
           [1, 2, 3, 4]])
    
    In [44]: ar = np.array([4,9,3,6,1,2])
    
    In [45]: strided_method(ar)
    Out[45]: 
    array([[2, 4, 9, 3, 6, 1],
           [1, 2, 4, 9, 3, 6],
           [6, 1, 2, 4, 9, 3],
           [3, 6, 1, 2, 4, 9],
           [9, 3, 6, 1, 2, 4],
           [4, 9, 3, 6, 1, 2]])
    

    运行时测试-

    In [5]: a = np.random.randint(0,9,(1000))
    
    # @Eric's soln
    In [6]: %timeit roll_matrix(a)
    100 loops, best of 3: 3.39 ms per loop
    
    # @Warren Weckesser's soln
    In [8]: %timeit circulant(a[::-1])
    100 loops, best of 3: 2.03 ms per loop
    
    # Strides method
    In [18]: %timeit strided_method(a)
    100000 loops, best of 3: 6.7 µs per loop
    

    制作副本(如果您想进行更改,而不仅仅是用作只读数组),对于该strides方法不会对我们造成太大的伤害-

    In [19]: %timeit strided_method(a).copy()
    1000 loops, best of 3: 381 µs per loop
    


知识点
面圈网VIP题库

面圈网VIP题库全新上线,海量真题题库资源。 90大类考试,超10万份考试真题开放下载啦

去下载看看