Home > Enterprise >  MATLAB/Numpy matrix slicing equivalent
MATLAB/Numpy matrix slicing equivalent

Time:10-15

I'm dealing with a MATLAB to Python code porting and I've been struggling to reproduce what this part of code does using Numpy slicing because it allows negative indexing:

A_new = [A(:, 1:i-1) v1 v2 A(:, i 1:size(A,2))];

Let's see a few cases:

i = 1;
A = [1; 1; 1; 1; 1];
v1 = [1; 1; 0; 0; 0];
v2 = [0; 0; 1; 1; 1];

A(:, 1:i-1) % column slicer is 1:i-1 which is 1:0 and therefore returns empty
   Empty matrix: 5-by-0

A(:, i 1:size(A,2)) % column slicer is i 1:size(A,2) which is 2:1 and therefore returns empty
   Empty matrix: 5-by-0

[A(:, 1:i-1) v1 v2 A(:, i 1:size(A,2))] % the result is just v1 and v2 stacked:
     1     0
     1     0
     0     1
     0     1
     0     1
i = 1;
A = [1 0; 1 0; 0 1; 0 1; 0 1];
v1 = [0; 1; 0; 0; 0];
v2 = [1; 0; 0; 0; 0];

A(:, 1:i-1) % column slicer is 1:i-1 which is 1:0 and therefore returns empty
   Empty matrix: 5-by-0

A(:, i 1:size(A,2)) % column slicer is i 1:size(A,2) which is 2:2 and therefore returns
     0
     0
     1
     1
     1

[A(:, 1:i-1) v1 v2 A(:, i 1:size(A,2))] % the result is v1, v2 and last column of A stacked:
     0     1     0
     1     0     0
     0     0     1
     0     0     1
     0     0     1

I'm not assuming it's correct and there are probably better approaches to achieve the same result, but this is how I replicated it in Python:

z, k = A.shape
ls = np.zeros((z, 0), dtype=float) if i - 1 < 0 else A[:, 0:(i - 1)]
rs = np.zeros((z, 0), dtype=float) if k < i   1 else A[:, (i   1):k]
a_new = np.hstack((ls, v1, v2, rs))

The first case works as expected. The second one is failing:

i = 0
A = np.asarray([[1., 0.], [1., 0.], [0., 1.], [0., 1.], [0., 1.]])
v1 = np.asarray([[0., 1., 0., 0., 0.]]).T
v2 = np.asarray([[1., 0., 0., 0., 0.]]).T

# LS: i - 1 < 0 | 0 - 1 < 0 | -1 < 0 ... LS is correctly evaluated as np.zeros((z, 0), dtype=float)

# RS: k < i   1 | 1 < 0   1 | 1 < 1 ... therefore RS is evaluated as A[:, (i   1):k]
# This should translate into A[:, 1:1] and take the last column of A, but instead it returns an empty ndarray with the following error:
    File "...\lib\site-packages\numpy\core\_methods.py", line 44, in _amin
    return umr_minimum(a, axis, None, out, keepdims, initial, where)
    ValueError: zero-size array to reduction operation minimum which has no identity

CodePudding user response:

First in your code:

z, k = a.shape

I think it's:

z, k = A.shape

Because you didn't define the variable a in the code python.

Now we check the shape of the variables in the python code a_new = np.hstack((ls, v1, v2, rs)):

print(ls.shape)
print(v1.shape)
print(v2.shape)
print(rs.shape)

The outputs :

(5, 0)
(1, 5)
(1, 5)
(5, 1)

So we know that the problem is the inconsistent dimension when calling the function np.hstack, just adjust the dimension of v1, v2 during defining theses two variables by transposing the vector:

v1 = np.asarray([[0., 1., 0., 0., 0.]]).T
v2 = np.asarray([[1., 0., 0., 0., 0.]]).T

Then we got:

a_new = np.hstack((ls, v1, v2, rs))
print(a_new )

[[0. 1. 0.]
 [1. 0. 0.]
 [0. 0. 1.]
 [0. 0. 1.]
 [0. 0. 1.]]

CodePudding user response:

If A is (5,1), then this indexing produces two (5,0) arrays:

In [141]: A = np.ones((5,1),int)
In [142]: i=0; A[:,:A.shape[1]-2], A[:,i 1:]
Out[142]: (array([], shape=(5, 0), dtype=int64), 
           array([], shape=(5, 0), dtype=int64))

For a (5,2), the result is a (5,0) and (5,1)

In [143]: A = np.ones((5,2),int)
In [144]: i=0; A[:,:A.shape[1]-2], A[:,i 1:]
Out[144]: 
(array([], shape=(5, 0), dtype=int64),
 array([[1],
        [1],
        [1],
        [1],
        [1]]))

To fully test this I'd need to fireup Octave, and try some other A shapes, and other i.

  • Related