jrive
jrive

Reputation: 238

How to combine column vectors into a matrix

How do I combine multiple column vectors into a Matrix? For example, if I have 3 10 x 1 vectors, how do I put them into a 10 x 3 matrix? Here's what I've tried so far:

D0 =np.array([[np.cos(2*np.pi*f*time)],[np.sin(2*np.pi*f*time)],np.ones((len(time),1)).transpose()],'float').transpose()

this gives me something like this ,

[[[ 1.00000000e+00  0.00000000e+00  1.00000000e+00]]

 [[ 9.99999741e-01  7.19053432e-04  1.00000000e+00]]

 [[ 9.99998966e-01  1.43810649e-03  1.00000000e+00]]

 ...

 [[ 9.99998966e-01 -1.43810649e-03  1.00000000e+00]]

 [[ 9.99999741e-01 -7.19053432e-04  1.00000000e+00]]

 [[ 1.00000000e+00 -2.15587355e-14  1.00000000e+00]]]

but, I don't think this is right, it looks more like an array of lists (and I couldn't do matrix multiplication with this form)...I tried numpy.concatenate as well, but that didn't work for me either...Looking into stack next....

In Matlab notation, I need to get this into a form

D0 =[cos(2*pi*f *t1), sin(2*pi*f*t1) ,1; cos(2*pi*f*t2), sin(2*pi*f*t2) ,1;....] etc

So that I can find the least squares solution s_hat:

s_hat = (D0^T D0)^-1(D0^T x)

where x is another input vector containing the samples of the sinusoid I'm trying to fit.

In Matlab, I could just type

D0 = [cos(2*np.pi*f*time),sin(2*np.pi*f*time), repmat(1,len(time),1)]

to create the D0 matrix. How do I do this in python?

Thank you!

Upvotes: 3

Views: 24236

Answers (2)

hpaulj
hpaulj

Reputation: 231395

If the arrays really are (10,1) shape, then simply concatenate:

In [60]: x,y,z = np.ones((10,1),int), np.zeros((10,1),int), np.arange(10)[:,None]              
In [61]: np.concatenate([x,y,z], axis=1)                                                       
Out[61]: 
array([[1, 0, 0],
       [1, 0, 1],
       [1, 0, 2],
       [1, 0, 3],
       [1, 0, 4],
       [1, 0, 5],
       [1, 0, 6],
       [1, 0, 7],
       [1, 0, 8],
       [1, 0, 9]])

If they are actually 1d, you'll have to fiddle with dimensions in one way or other. For example reshape or add a dimension as I did with z above. Or use some function that does that for you:

In [62]: x,y,z = np.ones((10,),int), np.zeros((10,),int), np.arange(10)                        
In [63]: z.shape                                                                               
Out[63]: (10,)
In [64]: np.array([x,y,z]).shape                                                               
Out[64]: (3, 10)
In [65]: np.array([x,y,z]).T       # transpose                                                            
Out[65]: 
array([[1, 0, 0],
       [1, 0, 1],
       [1, 0, 2],
       [1, 0, 3],
       [1, 0, 4],
       [1, 0, 5],
       [1, 0, 6],
       [1, 0, 7],
       [1, 0, 8],
       [1, 0, 9]])

np.array([...]) joins the arrays on a new initial dimension. Remember in Python/numpy the first dimension is the outermost one (MATLAB is the reverse).

stack variants tweak the dimensions, and then do concatenate:

In [66]: np.stack([x,y,z],axis=1).shape                                                        
Out[66]: (10, 3)
In [67]: np.column_stack([x,y,z]).shape                                                        
Out[67]: (10, 3)
In [68]: np.vstack([x,y,z]).shape                                                              
Out[68]: (3, 10)

===

D0 =np.array([[np.cos(2*np.pi*f*time)],[np.sin(2*np.pi*f*time)],np.ones((len(time),1)).transpose()],'float').transpose()

I'm guessing f is a scalar, and time is a 1d array (shape (10,))

[np.cos(2*np.pi*f*time)]

wraps a (10,) in [], which when turned into an array becomes (1,10) shape.

np.ones((len(time),1)).transpose() is (10,1) transposed to (1,10).

np.array(....) of these creates a (3,1,10) array. Transpose of that is (10,1,3).

If you dropped the [] and shape that created (1,10) arrays:

D0 =np.array([np.cos(2*np.pi*f*time), np.sin(2*np.pi*f*time), np.ones((len(time))]).transpose()

would join 3 (10,) arrays to make (3,10), which then transposes to (10,3).

Alternatively,

D0 =np.concatenate([[np.cos(2*np.pi*f*time)], [np.sin(2*np.pi*f*time)], np.ones((1,len(time),1))], axis=0)

joins the 3 (1,10) arrays to make a (3,10), which you can transpose.

Upvotes: 4

jmd_dk
jmd_dk

Reputation: 13100

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.

Upvotes: 4

Related Questions