Put A Vector Inside A Matrix + Transformation
So i have a vector created with Numpy called V = [10 20 30 40 0 1] And i want a matrix M like this : [10. 0. 0. 0. 0. 0.] [20. 10. 0. 0. 0. 0.] [30. 20. 10. 0. 0.
Solution 1:
If you only want a fast solution and not a solution which avoids loops you can simply use Numba
or Cython
.
Example
import numpy as np
import numba as nb
@nb.njit()defcreate_mat(V):
arr=np.zeros((V.shape[0],V.shape[0]),dtype=V.dtype)
for i inrange(V.shape[0]):
for j inrange(i,V.shape[0]):
arr[i,j]=V[j-i]
return arr
Timings
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
Solution 2:
Here is a vectorized approach:
In [74]: ind = np.arange(6)
In [75]: indices = ((ind[:,None] + ind).ravel() , np.repeat(ind, 6))
In [76]: base = np.zeros((11, 6))
In [77]: base[indices] = np.tile(V, 6)
In [78]: base
Out[78]:
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.]])
Solution 3:
Yes, for an array v
, we can first construct an numpy array with len(v)extra
0`s:
n = len(V)
m = np.tile(np.concatenate((V, np.zeros(n))), n)[:2*n*n-n]
result = m.reshape(n, 1).T
For the given V
list, this gives us:
>>> 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.]])
For a numpy array containing 500 elements, and 10'000 runs, we obtain:
>>>timeit(f, number=10000)
5.285840999999891
So converting a single array with 500 elements takes on my machine, 0.5 milliseconds. Constructing all these arrays will thus, approximately, take 52.86 seconds.
EDIT: I implemented the three attempts as follows:
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
and generated a random array with 500 elements:
V = np.random.randn(500)
then we ran tests with:
>>>timeit(wil, number=10000)
3.461620999999923
>>>timeit(mii, number=10000)
13.704932000000099
>>>timeit(kas, number=10000)
159.63497699999994
Solution 4:
Use the following:
from scipy.linalgimport toeplitz
res=np.tril(toeplitz(V).T
output:
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]])
Post a Comment for "Put A Vector Inside A Matrix + Transformation"