所以我有一个用Numpy创建的向量
V = [10 20 30 40 0 1]
我想要这样的矩阵M:
[10. 0. 0. 0. 0. 0.]
[20. 10. 0. 0. 0. 0.]
[30. 20. 10. 0. 0. 0.]
[40. 30. 20. 10. 0. 0.]
[ 0. 40. 30. 20. 10. 0.]
[ 1. 0. 40. 30. 20. 10.]
[ 0. 1. 0. 40. 30. 20.]
[ 0. 0. 1. 0. 40. 30.]
[ 0. 0. 0. 1. 0. 40.]
[ 0. 0. 0. 0. 1. 0.]
[ 0. 0. 0. 0. 0. 1.]
为此,我将其用于循环和矢量提取,但由于我的矢量V有500列并且矩阵M有500*2 -1
行和500
列,所以它太长了。
此外,对于不同的向量V,我必须重复至少10万次
是否可以使用矩阵计算并避免循环来获得此结果? (尽快)
谢谢!
(我在Spyder上使用Python 3.6)
编辑:我的解决方案:
t = 480 n = 10000
t1 = time.time()
for p in range(n):
for j in range(M.shape[1]):
M[j:j+t,j] = np.transpose(V[:])
print(time.time()-t1)
14秒仅10000次...太长了
编辑2:评论中解决方案的基准:
(这里Prate为V)
t1 = time.time()
for p in range(n):
for j in range(M.shape[1]):
M[j:j+t,j] = np.transpose(Prate[:])
print(time.time()-t1)
t1 = time.time()
for p in range(n):
n = len(Prate)
m = np.tile(np.concatenate((np.array(Prate), np.zeros(t))), t)[:2*t*t-t]
result = m.reshape(t, -1).T
print(time.time()-t1)
t1 = time.time()
for p in range(n):
ind = np.arange(t)
indices = ((ind[:,None] + ind).ravel() , np.repeat(ind, t))
base = np.zeros((n1, t))
base[indices] = np.tile(Prate, t)
print(time.time()-t1)
输出:
16.737313747406006
29.46031618118286
3.6843104362487793
编辑3 :为了避免遍历两倍于所需大小的数组,我提出了不同的问题:
我有一个向量(1x6):
V = [1 20 5 0 0 9]
我想要这样的矩阵M(6x6):
[1. 20. 5. 0. 0. 9.]
[0. 1. 20. 5. 0. 0.]
[0. 0. 1. 20. 5. 0.]
[0. 0. 0. 1. 20. 5.]
[0. 0. 0. 0. 1. 20.]
[0. 0. 0. 0. 0. 1.]
每行都是相同的向量V(它的一部分),但有一个偏移量以获得三角形矩阵。
如何做到没有循环?
(这只是一个简单的示例,但实向量V更大)
谢谢:D
答案 0 :(得分:0)
是的,对于数组v
,我们首先可以用len(v)extra
0`s构建一个numpy数组:
n = len(V)
m = np.tile(np.concatenate((V, np.zeros(n))), n)[:2*n*n-n]
result = m.reshape(n, 1).T
对于给定的V
列表,这给我们:
>>> np.tile(np.concatenate((V, np.zeros(n))), n)[:2*n*n-n].reshape(n,-1).T
array([[10., 0., 0., 0., 0., 0.],
[20., 10., 0., 0., 0., 0.],
[30., 20., 10., 0., 0., 0.],
[40., 30., 20., 10., 0., 0.],
[ 0., 40., 30., 20., 10., 0.],
[ 1., 0., 40., 30., 20., 10.],
[ 0., 1., 0., 40., 30., 20.],
[ 0., 0., 1., 0., 40., 30.],
[ 0., 0., 0., 1., 0., 40.],
[ 0., 0., 0., 0., 1., 0.],
[ 0., 0., 0., 0., 0., 1.]])
对于包含500个元素并运行1万次的numpy数组,我们获得:
>>> timeit(f, number=10000)
5.285840999999891
因此,转换具有500个元素的单个数组在我的机器上需要0.5毫秒。因此,构造所有这些数组大约需要52.86秒。
编辑:我实现了以下三种尝试:
def wil():
n = len(V)
return np.tile(np.concatenate((V, np.zeros(n))), n)[:2*n*n-n].reshape(n,-1).T
def mii():
n = len(V)
M = np.zeros((2*n-1, n))
for j in range(n):
M[j:j+n,j] = np.transpose(V[:])
return M
def kas():
n = len(V)
ind = np.arange(n)
indices = ((ind[:,None] + ind).ravel() , np.repeat(ind, n))
base = np.zeros((2*n-1, n))
base[indices] = np.tile(V, n)
return base
并生成具有500个元素的随机数组:
V = np.random.randn(500)
然后我们使用以下命令进行测试:
>>> timeit(wil, number=10000)
3.461620999999923
>>> timeit(mii, number=10000)
13.704932000000099
>>> timeit(kas, number=10000)
159.63497699999994
答案 1 :(得分:0)
这是一种矢量化方法:
FreeBooksProductId
答案 2 :(得分:0)
如果您只需要一种快速的解决方案,而又不想避免出现循环的解决方案,则可以简单地使用Numba
或Cython
。
示例
import numpy as np
import numba as nb
@nb.njit()
def create_mat(V):
arr=np.zeros((V.shape[0],V.shape[0]),dtype=V.dtype)
for i in range(V.shape[0]):
for j in range(i,V.shape[0]):
arr[i,j]=V[j-i]
return arr
时间
V=np.random.rand(10000)
#The first call has an constant compilation overhead of about 0.2s,
#which is neglected here.
create_mat: 0.35s
答案 3 :(得分:0)
使用以下内容:
from scipy.linalg import toeplitz
res=np.tril(toeplitz(V).T
输出:
res
>>array([[10, 20, 30, 40, 0, 1],
[ 0, 10, 20, 30, 40, 0],
[ 0, 0, 10, 20, 30, 40],
[ 0, 0, 0, 10, 20, 30],
[ 0, 0, 0, 0, 10, 20],
[ 0, 0, 0, 0, 0, 10]])