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.35sSolution 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)extra0`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).Toutput:
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"