在一个新的二维数组中,每一行都将向右移动一个一维numpy数组。

3
我将尽力为您翻译相关IT技术内容。以下是需要翻译的文本:

我正在尝试通过删除for循环并仅使用numpy数组来优化一些代码,因为我正在处理大型数据集。

例如,我想处理一个1D numpy数组:

a = [1, 2, 3, 4, 5]

我希望您能编写一个函数,生成一个2D numpy数组,其中每个列中的值向右移动一位。例如,在上面的示例中,如果我想要一个返回以下结果的函数:

[[1 2 3 4 5]
 [0 1 2 3 4]
 [0 0 1 2 3]
 [0 0 0 1 2]
 [0 0 0 0 1]]

我发现有些示例使用strides函数来做类似于produce的事情,例如:
[[1 2 3]
 [2 3 4]
 [3 4 5]]

然而,我正在尝试将我的每一列向另一个方向移动。或者,可以将问题视为将a的第一个元素放在第一条对角线上,第二个元素放在第二条对角线上,依此类推。然而,我想再次强调,我希望完全避免使用for、while或if循环。非常感谢任何帮助。

2个回答

4

这样的矩阵是托普利茨矩阵的一个例子。您可以使用scipy.linalg.toeplitz来创建它:

In [32]: from scipy.linalg import toeplitz

In [33]: a = range(1,6)

In [34]: toeplitz(a, np.zeros_like(a)).T
Out[34]: 
array([[1, 2, 3, 4, 5],
       [0, 1, 2, 3, 4],
       [0, 0, 1, 2, 3],
       [0, 0, 0, 1, 2],
       [0, 0, 0, 0, 1]])

受 @EelcoHoogendoorn 答案的启发,这里提供一种不像 scipy.linalg.toeplitz 那样使用大量内存的变体:
In [47]: from numpy.lib.stride_tricks import as_strided

In [48]: a
Out[48]: array([1, 2, 3, 4, 5])

In [49]: t = as_strided(np.r_[a[::-1], np.zeros_like(a)], shape=(a.size,a.size), strides=(a.itemsize, a.itemsize))[:,::-1]

In [50]: t
Out[50]: 
array([[1, 2, 3, 4, 5],
       [0, 1, 2, 3, 4],
       [0, 0, 1, 2, 3],
       [0, 0, 0, 1, 2],
       [0, 0, 0, 0, 1]])

结果应该被视为“只读”数组。否则,当您更改元素时,您将遇到一些意外情况。例如:
In [51]: t[0,2] = 99

In [52]: t
Out[52]: 
array([[ 1,  2, 99,  4,  5],
       [ 0,  1,  2, 99,  4],
       [ 0,  0,  1,  2, 99],
       [ 0,  0,  0,  1,  2],
       [ 0,  0,  0,  0,  1]])

或者使用 triu(circulant(a).T),但一些计时测试表明你的方法始终更快。 - DSM

2
这里是基于索引技巧的解决方案。虽然不像已发布的 Toeplitz 解决方案那么优雅,但如果关心内存消耗或性能,则更为推荐。正如演示的那样,这也使得随后以一致的方式操作矩阵的条目变得容易。
import numpy as np
a = np.arange(5)+1

def toeplitz_view(a):
    b = np.concatenate((np.zeros_like(a),a))
    i = a.itemsize
    v = np.lib.index_tricks.as_strided(b,
        shape=(len(b),)*2,
        strides=(-i, i))
    #return a view on the 'original' data as well, for manipulation
    return v[:len(a), len(a):], b[len(a):]        

v, a = toeplitz_view(a)
print v
a[0] = 10
v[2,1] = -1
print v

很好地运用了as_strided!为了好玩,这里有一行相当密集的代码:as_strided(np.r_[a[::-1], np.zeros_like(a)], shape=(a.size,a.size), strides=(a.itemsize, a.itemsize))[:,::-1] - Warren Weckesser

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