Skip to content Skip to sidebar Skip to footer

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)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).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"