[英]mapping a 2d delay vector from a 1d vector in numpy
我试图从1D向量生成2D向量,其中元素沿着行移动每行的增量。
我希望我的输入看起来像这样:
input:
t = [t1, t2, t3, t4, t5]
out =
[t5, 0, 0, 0, 0]
[t4, t5, 0, 0, 0]
[t3, t4, t5, 0, 0]
[t2, t3, t4, t5, 0]
[t1, t2, t3, t4, t5]
[ 0, t1, t2, t3, t4]
[ 0, 0, t1, t2, t3]
[ 0, 0, 0, t1, t2]
[ 0, 0, 0, 0, t1]
我没有意识到没有使用for循环的方法,并且计算效率对于使用它的任务非常重要。 没有for循环有没有办法做到这一点?
这是我使用for循环的代码:
import numpy as np
t = np.linspace(-3, 3, 7)
z = np.zeros((2*len(t) - 1, len(t)))
diag = np.arange(len(t))
for index, val in enumerate(np.flip(t, 0)):
z[diag + index, diag] = val
print(z)
你在这里要求的是一个Toeplitz矩阵 ,它是:
一个矩阵,其中每个从左到右的下降对角线是恒定的
一个区别是你想要矩阵的下三角形。
你碰巧运气好,你可以使用scipy.linalg.toeplitz
构建矩阵,然后使用np.tril
来访问下三角形。
import numpy as np
from scipy.linalg import toeplitz
v = np.array([1, 2, 3, 4, 5])
t = np.pad(v[::-1], (0, 4), mode='constant')
求解矩阵并访问下三角形:
np.tril(toeplitz(t, v))
而我们的输出!
array([[5, 0, 0, 0, 0],
[4, 5, 0, 0, 0],
[3, 4, 5, 0, 0],
[2, 3, 4, 5, 0],
[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]])
要概括此方法,只需从v
的形状计算t
的必要填充:
v = # any one dimension array
t = np.pad(v[::-1], (0, v.shape[0]-1), mode='constant')
不知道非循环方法,但你可以使用roll
和column_stack
加快速度。
v = np.array([1, 2, 3, 4, 5])
t = np.pad(v[::-1], (0, 4), mode='constant')
np.column_stack([np.roll(t, i) for i in range(len(v))])
array([[5, 0, 0, 0, 0],
[4, 5, 0, 0, 0],
[3, 4, 5, 0, 0],
[2, 3, 4, 5, 0],
[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-tricks
矢量化方法,它只是将视图用于零填充数组,并且是一种视图,其内存效率高,因此性能良好 -
def map2D(a):
n = len(a)
p = np.zeros(n-1,dtype=a.dtype)
a_ext = np.r_[p,a,p]
s0 = a_ext.strides[0]
strided = np.lib.stride_tricks.as_strided
return strided(a_ext[-n:], (len(a_ext)-n+1,n), (-s0,s0), writeable=False)
样品运行 -
In [81]: a = np.array([2,5,6,7,9])
In [82]: map2D(a)
Out[82]:
array([[9, 0, 0, 0, 0],
[7, 9, 0, 0, 0],
[6, 7, 9, 0, 0],
[5, 6, 7, 9, 0],
[2, 5, 6, 7, 9],
[0, 2, 5, 6, 7],
[0, 0, 2, 5, 6],
[0, 0, 0, 2, 5],
[0, 0, 0, 0, 2]])
如果您需要输出有自己的内存空间,请使用.copy()
5k
元素阵列上的时间 -
In [83]: a = np.random.randint(0,9,(5000))
# From this post's soln
In [84]: %timeit map2D(a)
10000 loops, best of 3: 26.3 µs per loop
# If you need output with its own memory space
In [97]: %timeit map2D(a).copy()
10 loops, best of 3: 43.6 ms per loop
# @user3483203's soln
In [87]: %%timeit
...: t = np.pad(a[::-1], (0, len(a)-1), mode='constant')
...: out = np.tril(toeplitz(t, a))
1 loop, best of 3: 264 ms per loop
# @coldspeed's soln
In [89]: %%timeit
...: t = np.pad(a[::-1], (0, len(a)-1), mode='constant')
...: out = np.column_stack([np.roll(t, i) for i in range(len(a))])
1 loop, best of 3: 336 ms per loop
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.