sam
sam

Reputation: 19164

dimension error while converting code from matlab to python

I am working on conversion of code from matlab to python.

for values,

N = 100
V = [[ -7.94627203e+01  -1.81562235e+02  -3.05418070e+02  -2.38451033e+02][  9.43740653e+01   1.69312771e+02   1.68545575e+01  -1.44450299e+02][  5.61599000e+00   8.76135909e+01   1.18959245e+02  -1.44049237e+02]]

V is numpy array.

for i = 1:N
    L(i) = sqrt(norm(v(:,i)));
    if L(i) > 0.0001
        q(:,i) = v(:,i)/L(i);
    else
        q(:,i) = v(:,i)*0.0001;
    end
end

I have converted this code to :

L = []
q = []


for i in range(1, (N +1)):
    L.insert((i -1),np.sqrt( np.linalg.norm(v[:, (i -1)])))
    if L[(i -1)] > 0.0001:
        q.insert((i -1), (v[:, (i -1)] / L[(i -1)]).tolist())
    else:
        q.insert((i -1), (v[:, (i -1)] * 0.0001).tolist())
q = np.array(q)
return q, len_

But, in matlab the resultant dimensions are 3 x 4 but I am getting 4 x 3 in python. Can anyone let me know where I am doing mistake?

Upvotes: 1

Views: 89

Answers (1)

Warren Weckesser
Warren Weckesser

Reputation: 114851

You are inserting lists of length 3 into q. When you finish the loop that creates q, q is a list of 4 items, where each item is a list of length 3. So np.array(q) creates an array with shape 4x3. You could change the second-to-last line to this:

q = np.array(q).T

Or, you can use numpy more effectively to eliminate all the explicit for loops. For example, if you are using numpy 1.8, the norm function accepts an axis argument.

Here's vectorized version of your code.

First, some setup for this example.

In [152]: np.set_printoptions(precision=3)

In [153]: np.random.seed(111)

Create some data to work with.

In [154]: v = 5e-9 * np.random.randint(0, 3, size=(3, 4))

In [155]: v
Out[155]: 
array([[  0.000e+00,   0.000e+00,   0.000e+00,   0.000e+00],
       [  1.000e-08,   5.000e-09,   1.000e-08,   1.000e-08],
       [  1.000e-08,   0.000e+00,   5.000e-09,   0.000e+00]])

Compute the square root of the norms of the columns by using the argument axis=0 in numpy.linalg.norm.

In [156]: L = np.sqrt(np.linalg.norm(v, axis=0))

In [157]: L
Out[157]: array([  1.189e-04,   7.071e-05,   1.057e-04,   1.000e-04])

Use numpy.where to select the values by which the columns of v are to be divided to create q.

In [158]: scale = np.where(L > 0.0001, L, 1000.0)

In [159]: scale
Out[159]: array([  1.189e-04,   1.000e+03,   1.057e-04,   1.000e+03])

q is has shape (3, 4), and scale has shape (4,), so we can use broadcasting to divide each column of q by the corresponding value in scale.

In [160]: q = v / scale

In [161]: q
Out[161]: 
array([[  0.000e+00,   0.000e+00,   0.000e+00,   0.000e+00],
       [  8.409e-05,   5.000e-12,   9.457e-05,   1.000e-11],
       [  8.409e-05,   0.000e+00,   4.729e-05,   0.000e+00]])

Repeated here are the three lines of the vectorized code:

L = np.sqrt(np.linalg.norm(v, axis=0))
scale = np.where(L > 0.0001, L, 1000.0)
q = v / scale

Upvotes: 1

Related Questions