简体   繁体   中英

Numpy array and Matlab Matrix are mismatching [3D]

The following octave code shows a sample 3D matrix using Octave/Matlab

octave:1> A=zeros(3,3,3);
octave:2> 
octave:2> A(:,:,1)= [[1 2 3];[4 5 6];[7 8 9]];
octave:3> 
octave:3> A(:,:,2)= [[11 22 33];[44 55 66];[77 88 99]];
octave:4> 
octave:4> A(:,:,3)= [[111 222 333];[444 555 666];[777 888 999]];
octave:5> 
octave:5> 
octave:5> A
A =

ans(:,:,1) =

   1   2   3
   4   5   6
   7   8   9

ans(:,:,2) =

   11   22   33
   44   55   66
   77   88   99

ans(:,:,3) =

   111   222   333
   444   555   666
   777   888   999

octave:6> A(1,3,2)
ans =  33

And I need to convert the same matrix using numpy ... unfortunately When I'm trying to access the same index using array in numpy I get different values as shown below!!

import numpy as np
array = np.array([[[1 ,2 ,3],[4 ,5 ,6],[7 ,8 ,9]], [[11 ,22 ,33],[44 ,55 ,66],[77 ,88 ,99]], [[111 ,222 ,333],[444 ,555 ,666],[777 ,888 ,999]]])
>>> array[0,2,1]
8

Also I read the following document that shows the difference between matrix implementation in Matlab and in Python numpy Numpy for Matlab users but I didn't find a sample 3d array and the mapping of it into Matlab and vice versa!

the answer is different for example accessing the element(1,3,2) in Matlab doesn't match the same index using numpy (0,2,1)

Octave/Matlab

octave:6> A(1,3,2)

ans = 33

Python

>>> array[0,2,1]

8

The way your array is constructed in numpy is different than it is in MATLAB.

Where your MATLAB array is (y, x, z) , your numpy array is (z, y, x) . Your 3d numpy array is a series of 'stacked' 2d arrays, so you're indexing "outside->inside" (for lack of a better term). Here's your array definition expanded so this (hopefully) makes a little more sense:

[[[1, 2, 3],
  [4, 5, 6],        # Z = 0
  [7 ,8 ,9]],
 [[11 ,22 ,33],
  [44 ,55 ,66],     # Z = 1
  [77 ,88 ,99]],
 [[111 ,222 ,333],
  [444 ,555 ,666],  # Z = 2
  [777 ,888 ,999]]
]

So with:

import numpy as np

A = np.array([[[1 ,2 ,3],[4 ,5 ,6],[7 ,8 ,9]], [[11 ,22 ,33],[44 ,55 ,66],[77 ,88 ,99]], [[111 ,222 ,333],[444 ,555 ,666],[777 ,888 ,999]]])
B = A[1, 0, 2]

B returns 33 , as expected.

If you want a less mind-bending way to indexing your array, consider generating it as you did in MATLAB.

MATLAB and Python index differently. To investigate this, lets create a linear array of number 1 to 8 and then reshape the result to be a 2 -by- 2 -by- 2 matrix in each language:

MATLAB:

M_flat = 1:8
M = reshape(M_flat, [2,2,2])

which returns

M =

ans(:,:,1) =

   1   3
   2   4

ans(:,:,2) =

   5   7
   6   8

Python:

import numpy as np
P_flat = np.array(range(1,9))
P = np.reshape(P, [2,2,2])

which returns

array([[[1, 2],
        [3, 4]],

       [[5, 6],
        [7, 8]]])

The first thing you should notice is that the first two dimensions have switched. This is because MATLAB uses column-major indexing which means we count down the columns first whereas Python use row-major indexing and hence it counts across the rows first.

Now let's try indexing them. So let's try slicing along the different dimensions. In MATLAB, I know to get a slice out of the third dimension I can do

M(:,:,1)

ans =

   1   3
   2   4

Now let's try the same in Python

P[:,:,0]

array([[1, 3],
       [5, 7]])

So that's completely different. To get the MATLAB 'equivalent' we need to go

P[0,:,:]

array([[1, 2],
       [3, 4]])

Now this returns the transpose of the MATLAB version which is to be expected due the the row-major vs column-major difference.

So what does this mean for indexing? It looks like Python puts the major index at the end which is the reverse of MALTAB.

Let's say I index as follows in MATLAB

M(1,2,2)

ans = 

    7

now to get the 7 from Python we should go

P(1,1,0)

which is the MATLAB syntax reversed. Note that is is reversed because we created the Python matrix with a row-major ordering in mind. If you create it as you did in your code you would have to swap the last 2 indices so rather create the matrix correctly in the first place as Ander has suggested in the comments.

I think that the problem is the way you create the matrix in numpy and also the different representation of matlab and numpy, why you don't use the same system in matlab and numpy

>>> A = np.zeros((3,3,3),dtype=int)
>>> A
array([[[0, 0, 0],
        [0, 0, 0],
        [0, 0, 0]],

       [[0, 0, 0],
        [0, 0, 0],
        [0, 0, 0]],

       [[0, 0, 0],
        [0, 0, 0],
        [0, 0, 0]]])
>>> A[:,:,0] = np.array([[1,2,3],[4,5,6],[7,8,9]])
>>> A[:,:,1] = np.array([[11,22,33],[44,55,66],[77,88,99]])
>>> A[:,:,2] = np.array([[111,222,333],[444,555,666],[777,888,999]])
>>> A
array([[[  1,  11, 111],
        [  2,  22, 222],
        [  3,  33, 333]],

       [[  4,  44, 444],
        [  5,  55, 555],
        [  6,  66, 666]],

       [[  7,  77, 777],
        [  8,  88, 888],
        [  9,  99, 999]]])
>>> A[0,2,1]
33

I think better than just calling the difference "row major" or "column major" is numpy's way of describing them:

'C' means to read / write the elements using C-like index order, with the last axis index changing fastest, back to the first axis index changing slowest. 'F' means to read / write the elements using Fortran-like index order, with the first index changing fastest, and the last index changing slowest.

Some gifs to illustrate the difference: The first is row-major (python / c), second is column-major (MATLAB/ Fortran)

Python / C索引排序

MATLAB / Fortran索引排序

I think that python uses this type of indexing to create arrays as shown in the following figure:

https://www.google.com.eg/search?q=python+indexing+arrays+numpy&biw=1555&bih=805&source=lnms&tbm=isch&sa=X&ved=0ahUKEwia7b2J1qzOAhUFPBQKHXtdCBkQ_AUIBygC#imgrc=7JQu1w_4TCaAnM%3A

And, there are many ways to store your data, you can choose order='F' to count the columns first as matlab does, while the default is order='C' that count the rows first....

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM