【问题标题】:Numpy array and Matlab Matrix are mismatching [3D]Numpy 数组和 Matlab 矩阵不匹配 [3D]
【发布时间】:2016-08-05 12:37:57
【问题描述】:

以下 octave 代码显示了使用 Octave/Matlab 的示例 3D 矩阵

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

我需要使用 numpy 转换相同的矩阵......不幸的是,当我尝试使用 numpy 中的数组访问相同的索引时,我得到不同的值,如下所示!

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

我还阅读了以下文档,该文档显示了 Matlab 和 Python numpy Numpy for Matlab users 中的矩阵实现之间的区别,但我没有找到示例 3d 数组并将其映射到 Matlab 中,反之亦然!

答案是不同的,例如在 Matlab 中访问 element(1,3,2) 与使用 numpy (0,2,1) 的索引不匹配

Octave/Matlab

八度:6> A(1,3,2)

ans = 33

Python

>>> 数组[0,2,1]

8

【问题讨论】:

  • 我相信 MATLAB 是 A(x,y,z) 而 numpy 是 A[z,y,x]
  • @AnderBiguri 在 Python 中尝试,它看起来应该是 A[z,x,y],我认为 xy 切换是因为行主要与列主要的区别
  • @Dan 是的,当然,你是对的。从技术上讲,更改是反向暗淡+交换x,y,因为行/列主要。但是,这最后一个更改,我会将其添加到矩阵的 定义,而不是索引,因为这是所有 python 矩阵的创建方式
  • 基本上有2个不同。 1)见我的第一条评论。 2) A=[1 2; 3 4] 在 numpy 中是 A=np.array([[1, 3], [2, 4]])

标签: python arrays matlab numpy matrix


【解决方案1】:

在 numpy 中构造数组的方式与在 MATLAB 中不同。

你的 MATLAB 数组是 (y, x, z),你的 numpy 数组是 (z, y, x)。您的 3d numpy 数组是一系列“堆叠”的 2d 数组,因此您正在索引“outside->inside”(因为没有更好的术语)。这是您扩展的数组定义,因此(希望)这更有意义:

[[[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]]
]

所以:

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 按预期返回33

如果您想要一种不那么费脑筋的方式来索引您的数组,请考虑像在 MATLAB 中那样生成它。

【讨论】:

    【解决方案2】:

    MATLAB 和 Python 的索引不同。为了研究这个问题,让我们创建一个由18 组成的线性数组,然后reshape 结果是每种语言的2-by-2-by-2 矩阵:

    MATLAB:

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

    返回

    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])
    

    返回

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

    您应该注意到的第一件事是前两个维度已经切换。这是因为 MATLAB 使用列优先索引,这意味着我们首先倒数列,而 Python 使用行优先索引,因此它首先跨行计数。

    现在让我们尝试索引它们。因此,让我们尝试沿不同的维度进行切片。在 MATLAB 中,我知道从我能做的第三维中得到一个切片

    M(:,:,1)
    
    ans =
    
       1   3
       2   4
    

    现在让我们在 Python 中尝试同样的方法

    P[:,:,0]
    
    array([[1, 3],
           [5, 7]])
    

    所以这完全不同。要获得 MATLAB '等效',我们需要去

    P[0,:,:]
    
    array([[1, 2],
           [3, 4]])
    

    现在,这将返回 MATLAB 版本的转置,这是由于行主要与列主要差异而预期的。

    那么这对索引意味着什么?看起来 Python 将主要索引放在最后,这是 MALTAB 的反向

    假设我在 MATLAB 中的索引如下

    M(1,2,2)
    
    ans = 
    
        7
    

    现在要从 Python 中获取7,我们应该去

    P(1,1,0)
    

    这是颠倒的 MATLAB 语法。请注意,这是相反的,因为我们在创建 Python 矩阵时考虑了行优先排序。如果您像在代码中那样创建它,则必须交换最后 2 个索引,以便首先正确地创建矩阵,正如 Ander 在 cmets 中建议的那样。

    【讨论】:

      【解决方案3】:

      我认为 numpy 描述它们的方式比仅仅将差异称为“行专业”或“列专业”更好:

      ‘C’表示使用类似C的索引顺序读取/写入元素,最后一个轴索引变化最快,回到第一个轴索引变化最慢。 ‘F’ 表示使用类似 Fortran 的索引顺序读取/写入元素,第一个索引变化最快,最后一个索引变化最慢。

      一些gif来说明区别:第一个是row-major(python / c),第二个是column-major(MATLAB/ Fortran)

      【讨论】:

        【解决方案4】:

        我认为问题在于你在 numpy 中创建矩阵的方式以及 matlab 和 numpy 的不同表示,为什么你不在 matlab 和 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
        

        【讨论】:

          【解决方案5】:

          我认为python使用这种类型的索引来创建数组如下图所示:

          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

          而且,存储数据的方法有很多种,你可以像matlab一样选择order='F'先计算列数,而默认是order='C'先计算行数....

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2015-02-04
            • 1970-01-01
            • 1970-01-01
            • 2015-10-12
            • 1970-01-01
            • 2013-09-21
            • 1970-01-01
            相关资源
            最近更新 更多