Python 1D numpy数组,对于新2D数组中的每个连续行向右移动
我试图通过删除for循环和仅在处理大型数据集时使用numpy数组来优化一些代码 我想以1D numpy阵列为例:Python 1D numpy数组,对于新2D数组中的每个连续行向右移动,python,numpy,Python,Numpy,我试图通过删除for循环和仅在处理大型数据集时使用numpy数组来优化一些代码 我想以1D numpy阵列为例: a = [1, 2, 3, 4, 5] 并生成一个2D numpy数组,其中每列中的值沿一个位置移动,例如,在上面的例子中,对于a,我希望有一个函数返回: [[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]] 我发现了一些例子,它们使用步幅函数来做一些类似于生成的事情,例如: [[1 2 3] [2
a = [1, 2, 3, 4, 5]
并生成一个2D numpy数组,其中每列中的值沿一个位置移动,例如,在上面的例子中,对于a,我希望有一个函数返回:
[[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]]
我发现了一些例子,它们使用步幅函数来做一些类似于生成的事情,例如:
[[1 2 3]
[2 3 4]
[3 4 5]]
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]])
然而,我正试图将我的每一列移向另一个方向。或者,可以将问题视为将a的第一个元素放在第一条对角线上,将第二个元素放在第二条对角线上,依此类推。然而,我想再次强调,我希望避免完全使用for、while或if循环。任何帮助都将不胜感激 这样的矩阵就是一个例子。您可以使用创建它:
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]])
受@eelcoogendoorn答案的启发,这里有一个变体,它使用的内存不如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]])
结果应视为“只读”数组。否则,当您更改一个元素时,您将遇到一些惊喜。例如:
[[1 2 3]
[2 3 4]
[3 4 5]]
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]])
以下是基于索引技巧的解决方案。虽然不像已经发布的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
或者
triu(循环(a).T)
,但一些计时测试表明您的方式始终更快。这很好。非常感谢您-我从来没有在搜索中找到过这个函数。随着_ _的进步,巧妙地使用!对于踢腿,这里有一个相当密集的一行:as_stripped(np.r_[a[:-1],np.zero_像(a)],shape=(a.size,a.size),strippes=(a.itemsize,a.itemsize))[:,:-1]