Numpy - Create Matrix with Rows of Vector

Numpy - create matrix with rows of vector

Certainly possible with broadcasting after adding with m zeros along the columns, like so -

np.zeros((m,1),dtype=vector.dtype) + vector

Now, NumPy already has an in-built function np.tile for exactly that same task -

np.tile(vector,(m,1))

Sample run -

In [496]: vector
Out[496]: array([4, 5, 8, 2])

In [497]: m = 5

In [498]: np.zeros((m,1),dtype=vector.dtype) + vector
Out[498]:
array([[4, 5, 8, 2],
[4, 5, 8, 2],
[4, 5, 8, 2],
[4, 5, 8, 2],
[4, 5, 8, 2]])

In [499]: np.tile(vector,(m,1))
Out[499]:
array([[4, 5, 8, 2],
[4, 5, 8, 2],
[4, 5, 8, 2],
[4, 5, 8, 2],
[4, 5, 8, 2]])

You can also use np.repeat after extending its dimension with np.newaxis/None for the same effect, like so -

In [510]: np.repeat(vector[None],m,axis=0)
Out[510]:
array([[4, 5, 8, 2],
[4, 5, 8, 2],
[4, 5, 8, 2],
[4, 5, 8, 2],
[4, 5, 8, 2]])

You can also use integer array indexing to get the replications, like so -

In [525]: vector[None][np.zeros(m,dtype=int)]
Out[525]:
array([[4, 5, 8, 2],
[4, 5, 8, 2],
[4, 5, 8, 2],
[4, 5, 8, 2],
[4, 5, 8, 2]])

And finally with np.broadcast_to, you can simply create a 2D view into the input vector and as such this would be virtually free and with no extra memory requirement. So, we would simply do -

In [22]: np.broadcast_to(vector,(m,len(vector)))
Out[22]:
array([[4, 5, 8, 2],
[4, 5, 8, 2],
[4, 5, 8, 2],
[4, 5, 8, 2],
[4, 5, 8, 2]])

Runtime test -

Here's a quick runtime test comparing the various approaches -

In [12]: vector = np.random.rand(10000)

In [13]: m = 10000

In [14]: %timeit np.broadcast_to(vector,(m,len(vector)))
100000 loops, best of 3: 3.4 µs per loop # virtually free!

In [15]: %timeit np.zeros((m,1),dtype=vector.dtype) + vector
10 loops, best of 3: 95.1 ms per loop

In [16]: %timeit np.tile(vector,(m,1))
10 loops, best of 3: 89.7 ms per loop

In [17]: %timeit np.repeat(vector[None],m,axis=0)
10 loops, best of 3: 86.2 ms per loop

In [18]: %timeit vector[None][np.zeros(m,dtype=int)]
10 loops, best of 3: 89.8 ms per loop

Create a matrix from a vector where each row is a shifted version of the vector

Here's one approach using NumPy strides basically padding with the leftover elements and then the strides helping us in creating that shifted version pretty efficiently -

def strided_method(ar):
a = np.concatenate(( ar, ar[:-1] ))
L = len(ar)
n = a.strides[0]
return np.lib.stride_tricks.as_strided(a[L-1:], (L,L), (-n,n))

Sample runs -

In [42]: ar = np.array([1, 2, 3, 4])

In [43]: strided_method(ar)
Out[43]:
array([[4, 1, 2, 3],
[3, 4, 1, 2],
[2, 3, 4, 1],
[1, 2, 3, 4]])

In [44]: ar = np.array([4,9,3,6,1,2])

In [45]: strided_method(ar)
Out[45]:
array([[2, 4, 9, 3, 6, 1],
[1, 2, 4, 9, 3, 6],
[6, 1, 2, 4, 9, 3],
[3, 6, 1, 2, 4, 9],
[9, 3, 6, 1, 2, 4],
[4, 9, 3, 6, 1, 2]])

Runtime test -

In [5]: a = np.random.randint(0,9,(1000))

# @Eric's soln
In [6]: %timeit roll_matrix(a)
100 loops, best of 3: 3.39 ms per loop

# @Warren Weckesser's soln
In [8]: %timeit circulant(a[::-1])
100 loops, best of 3: 2.03 ms per loop

# Strides method
In [18]: %timeit strided_method(a)
100000 loops, best of 3: 6.7 µs per loop

Making a copy (if you want to make changes and not just use as a read only array) won't hurt us too badly for the strides method -

In [19]: %timeit strided_method(a).copy()
1000 loops, best of 3: 381 µs per loop

Adding a vector to matrix rows in numpy

For adding a 1d array to every row, broadcasting already takes care of things for you:

mat += vec

However more generally you can use np.newaxis to coerce the array into a broadcastable form. For example:

mat + np.ones(3)[np.newaxis,:]

While not necessary for adding the array to every row, this is necessary to do the same for column-wise addition:

mat + np.ones(5)[:,np.newaxis]

EDIT: as Sebastian mentions, for row addition, mat + vec already handles the broadcasting correctly. It is also faster than using np.newaxis. I've edited my original answer to make this clear.

How to concatenate a vector into rows of a numpy matrix?

output = np.zeros((2,4), int)
output[:, :2] = a # broadcasts (2,) to (1,2) to (2,2)
output[:, 2:] = b

How to build a numpy array row by row in a for loop?

A numpy array must be created with a fixed size. You can create a small one (e.g., one row) and then append rows one at a time, but that will be inefficient. There is no way to efficiently grow a numpy array gradually to an undetermined size. You need to decide ahead of time what size you want it to be, or accept that your code will be inefficient. Depending on the format of your data, you can possibly use something like numpy.loadtxt or various functions in pandas to read it in.

Python Numpy: Adding vector to existing matrix row

In [74]: A = np.arange(1,10).reshape(3,3); v = np.arange(1,4)                                                        
In [75]: A
Out[75]:
array([[1, 2, 3],
[4, 5, 6],
[7, 8, 9]])
In [77]: v
Out[77]: array([1, 2, 3])

Expand A to a (3,3,3):

In [78]: A[None,:,:].repeat(3,0)                                                                                     
Out[78]:
array([[[1, 2, 3],
[4, 5, 6],
[7, 8, 9]],

[[1, 2, 3],
[4, 5, 6],
[7, 8, 9]],

[[1, 2, 3],
[4, 5, 6],
[7, 8, 9]]])

Do the same with v:

In [79]: np.eye(3)                                                                                                   
Out[79]:
array([[1., 0., 0.],
[0., 1., 0.],
[0., 0., 1.]])
In [80]: np.eye(3)[:,:,None]*v
Out[80]:
array([[[1., 2., 3.],
[0., 0., 0.],
[0., 0., 0.]],

[[0., 0., 0.],
[1., 2., 3.],
[0., 0., 0.]],

[[0., 0., 0.],
[0., 0., 0.],
[1., 2., 3.]]])

add the two:

In [81]: _78+_80                                                                                                     
Out[81]:
array([[[ 2., 4., 6.],
[ 4., 5., 6.],
[ 7., 8., 9.]],

[[ 1., 2., 3.],
[ 5., 7., 9.],
[ 7., 8., 9.]],

[[ 1., 2., 3.],
[ 4., 5., 6.],
[ 8., 10., 12.]]])

or in one step:

A+np.eye(3)[:,:,None]*v  

How to combine column vectors into a matrix

Here you have equivalent complete examples in Matlab and Python/NumPy:

% Matlab
f = 0.1;
time = [0; 1; 2; 3];
D0 = [cos(2*pi*f*time), sin(2*pi*f*time), repmat(1,length(time),1)]
# Python
import numpy as np
f = 0.1
time = np.array([0, 1, 2, 3])
D0 = np.array([np.cos(2*np.pi*f*time), np.sin(2*np.pi*f*time), np.ones(time.size)]).T
print(D0)

Note that unlike Matlab, Python/NumPy has no special syntax to distinguish rows from columns (, vs. ; in Matlab). Similarly, a 1D NumPy array has no notion of either being a "column" or "row" vector. When merging several 1D NumPy arrays into a single 2D array, as above, each 1D array ends up as a row in the 2D array. As you want them as columns, you need to transpose the 2D array, here accomplished simply by the .T attribute.



Related Topics



Leave a reply



Submit